Java multithreading interview questions and answers
If you are going for Java interviews to work on large scale systems, expect multi-threading interview questions. These are more beginner or fresher level questions and if you are already good with the basics, try moreintermediate to advanced level coding questions and answers on Java multi-threading at Java multi-threading-1 | Java multi-threading-2
Q. What is the difference between processes and threads?
A. A process is an execution of a program but a thread is a single execution sequence within the process. A process can contain multiple threads. A thread is sometimes called a lightweight process.
A JVM runs in a single process and threads in a JVM share the heap belonging to that process. That is why several threads may access the same object. Threads share the heap and have their own stack space. This is how one thread’s invocation of a method and its local variables are kept thread safe from other threads. But the heap is not thread-safe and must be synchronized for thread safety.
Q. Explain different ways of creating a thread?
A. Threads can be used by either
The thread pool is more efficient and learn why and how to create pool of threads using the executor framework.
Q. Which one would you prefer and why?
A. The Runnable interface is preferred, as it does not require your object to inherit a thread because when you need multiple inheritance, only interfaces can help you. In the above example we had to extend the Base class so implementing Runnable interface is an obvious choice. Also note how the threads are started in each of the different cases as shown in the code sample. In an OO approach you should only extend a class when you want to make it different from it’s superclass, and change it’s behavior. By implementing a Runnable interface instead of extending the Thread class, you are telling to the user that the class Counter is an object of type Base and will run as a thread.
Q. Briefly explain high-level thread states?
A. The state chart diagram below describes the thread states.
Q. What is the difference between yield and sleeping? What is the difference between the methods sleep( ) and wait( )?
A. When a task invokes yield( ), it changes from running state to runnable state. When a task invokes sleep ( ), it changes from running state to waiting/sleeping state.
The method wait(1000), causes the current thread to sleep up to one second. A thread could sleep less than 1 second if it receives the notify( ) or notifyAll( ) method call. The call to sleep(1000) causes the current thread to sleep for 1 second.
Q. Why is locking of a method or block of code for thread safety is called "synchronized" and not "lock" or "locked"?
A. When a method or block of code is locked with the reserved "synchronized" key word in Java, the memory (i.e. heap) where the shared data is kept is synchronized. This means,
This is why it is called "synchronized" and not "locked". This is also the reason why the immutable objects are inherently thread-safe and does not require any synchronization. Once created, the immutable objects cannot be modified.
Q. How does thread synchronization occurs inside a monitor? What levels of synchronization can you apply? What is the difference between synchronized method and synchronized block?
A. In Java programming, each object has a lock. A thread can acquire the lock for an object by using the synchronized keyword. The synchronized keyword can be applied in method level (coarse grained lock – can affect performance adversely) or block level of code (fine grained lock). Often using a lock on a method level is too coarse. Why lock up a piece of code that does not access any shared resources by locking up an entire method. Since each object has a lock, dummy objects can be created to implement block level synchronization. The block level is more efficient because it does not lock the whole method.
The JVM uses locks in conjunction with monitors. A monitor is basically a guardian who watches over a sequence of synchronized code and making sure only one thread at a time executes a synchronized piece of code. Each monitor is associated with an object reference. When a thread arrives at the first instruction in a block of code it must obtain a lock on the referenced object. The thread is not allowed to execute the code until it obtains the lock. Once it has obtained the lock, the thread enters the block of protected code. When the thread leaves the block, no matter how it leaves the block, it releases the lock on the associated object. For static methods, you acquire a class level lock.
More Interview Q&A on Java multithreading:
Beginner:
Articles on Java 5 concurrent package
Q. What is the difference between processes and threads?
A. A process is an execution of a program but a thread is a single execution sequence within the process. A process can contain multiple threads. A thread is sometimes called a lightweight process.
A JVM runs in a single process and threads in a JVM share the heap belonging to that process. That is why several threads may access the same object. Threads share the heap and have their own stack space. This is how one thread’s invocation of a method and its local variables are kept thread safe from other threads. But the heap is not thread-safe and must be synchronized for thread safety.
Q. Explain different ways of creating a thread?
A. Threads can be used by either
- Extending the Thread class.
- Implementing the Runnable interface.
- Using the Executor framework (this creates a thread pool)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Counter extends Thread { //method where the thread execution will start public void run(){ //logic to execute in a thread } //let’s see how to start the threads public static void main(String[] args){ Thread t1 = new Counter(); Thread t2 = new Counter(); t1.start(); //start the first thread. This calls the run() method. t2.start(); //this starts the 2nd thread. This calls the run() method. } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Counter extends Base implements Runnable{ //method where the thread execution will start public void run(){ //logic to execute in a thread } //let us see how to start the threads public static void main(String[] args){ Thread t1 = new Thread( new Counter()); Thread t2 = new Thread( new Counter()); t1.start(); //start the first thread. This calls the run() method. t2.start(); //this starts the 2nd thread. This calls the run() method. } } |
The thread pool is more efficient and learn why and how to create pool of threads using the executor framework.
Q. Which one would you prefer and why?
A. The Runnable interface is preferred, as it does not require your object to inherit a thread because when you need multiple inheritance, only interfaces can help you. In the above example we had to extend the Base class so implementing Runnable interface is an obvious choice. Also note how the threads are started in each of the different cases as shown in the code sample. In an OO approach you should only extend a class when you want to make it different from it’s superclass, and change it’s behavior. By implementing a Runnable interface instead of extending the Thread class, you are telling to the user that the class Counter is an object of type Base and will run as a thread.
Q. Briefly explain high-level thread states?
A. The state chart diagram below describes the thread states.
- Runnable — A thread becomes runnable when you call the start( ), but does not necessarily start running immediately. It will be pooled waiting for its turn to be picked for execution by the thread scheduler based on thread priorities.12
MyThread aThread =
new
MyThread();
aThread.start();
//becomes runnable
- Running: The processor is actively executing the thread code. It runs until it becomes blocked, or voluntarily gives up its turn with this static method Thread.yield( ). Because of context switching overhead, yield( ) should not be used very frequently
- Waiting: A thread is in a blocked state while it waits for some external processing such as file I/O to finish.A call to currObject.wait( ) method causes the current thread to wait until some other thread invokes currObject.notify( ) or the currObject.notifyAll( ) is executed.
- Sleeping: Java threads are forcibly put to sleep (suspended) with this overloaded method: Thread.sleep(milliseconds), Thread.sleep(milliseconds, nanoseconds);
- Blocked on I/O: Will move to runnable after I/O condition like reading bytes of data etc changes.
- Blocked on synchronization: will move to running when a lock is acquired.
- Dead: The thread is finished working.
Thread.State enumeration contains the possible states of a Java thread in the underlying JVM. These thread states are possible due to Java's following thread concepts:
- The objects can be shared and modified (i.e. if mutable) by any threads.
- The preemptive nature of the thread scheduler can swap threads on and off cores in a multi-core CPU machine at any time.
- This means the methods can be swapped out while they are running. Otherwise a method in an infinite loop will clog the CPU forever leaving the other methods on different threads to starve.
- To prevent thread safety issues, the methods and block of code that has vulnerable data can belocked.
- This enables the threads to be in locked or waiting to acquire a lock states.
- The threads also get into the waiting state for I/O resources like sockets, file handles, and database connections.
- The threads that are performing I/O read/write operations can not be swapped. Hence, they need to either complete to the finished state with success/failure or another thread must close the socket for it to get to the state of dead or finished. This is why proper service timeout values are necessary to prevent the thread to get blocked for ever in an I/O operation, causing performance issues.
- The threads can be put to sleep to give other threads in waiting state an opportunity to execute.
Q. What is the difference between yield and sleeping? What is the difference between the methods sleep( ) and wait( )?
A. When a task invokes yield( ), it changes from running state to runnable state. When a task invokes sleep ( ), it changes from running state to waiting/sleeping state.
The method wait(1000), causes the current thread to sleep up to one second. A thread could sleep less than 1 second if it receives the notify( ) or notifyAll( ) method call. The call to sleep(1000) causes the current thread to sleep for 1 second.
Q. Why is locking of a method or block of code for thread safety is called "synchronized" and not "lock" or "locked"?
A. When a method or block of code is locked with the reserved "synchronized" key word in Java, the memory (i.e. heap) where the shared data is kept is synchronized. This means,
- When a synchronized block or method is entered after the lock has been acquired by a thread, it firstreads any changes to the locked object from the main heap memory to ensure that the thread that has the lock has the current info before start executing.
- After the synchronized block has completed and the thread is ready to relinquish the lock, all the changes that were made to the object that was locked is written or flushed back to the main heap memory so that the other threads that acquire the lock next has the current info.
This is why it is called "synchronized" and not "locked". This is also the reason why the immutable objects are inherently thread-safe and does not require any synchronization. Once created, the immutable objects cannot be modified.
Q. How does thread synchronization occurs inside a monitor? What levels of synchronization can you apply? What is the difference between synchronized method and synchronized block?
A. In Java programming, each object has a lock. A thread can acquire the lock for an object by using the synchronized keyword. The synchronized keyword can be applied in method level (coarse grained lock – can affect performance adversely) or block level of code (fine grained lock). Often using a lock on a method level is too coarse. Why lock up a piece of code that does not access any shared resources by locking up an entire method. Since each object has a lock, dummy objects can be created to implement block level synchronization. The block level is more efficient because it does not lock the whole method.
The JVM uses locks in conjunction with monitors. A monitor is basically a guardian who watches over a sequence of synchronized code and making sure only one thread at a time executes a synchronized piece of code. Each monitor is associated with an object reference. When a thread arrives at the first instruction in a block of code it must obtain a lock on the referenced object. The thread is not allowed to execute the code until it obtains the lock. Once it has obtained the lock, the thread enters the block of protected code. When the thread leaves the block, no matter how it leaves the block, it releases the lock on the associated object. For static methods, you acquire a class level lock.
More Interview Q&A on Java multithreading:
Beginner:
- Java multithreading questions and answers -- synchronization, daemon thread, inter thread communication
- Java coding question and answer on multi-threading
Intermediate to Advanced
- Java multi threading questions and answers -- coding
- Java multi threading questions and answers -- atomic operations
Articles on Java 5 concurrent package
- Article: Scenarios and solutions for better concurrency and thread safety part-2 CountDownLatch and CyclicBarrier
- Article: Scenarios and solutions for better concurrency and thread safety part-3 Semaphores and mutexes
Comments
Post a Comment