Java / Java Multithreading
We often multi task, listing to music while working or driving; Browsing internet while waiting for a download to complete.
Even every computer application do things parallel. An email software will be downloading new emails from the server while you are reading an already downloaded email, archive mails in the background, prompt meeting reminders while you are writing an email.
The Computer application that multi tasks is referred as concurrent software.
Java has the hight support for concurrent programming also with its APIs. (java.util.concurrent)
A computer or device running more than one application at the given time. For e.g. running mp3 player application while reading a blog using internet browser. Here mp3 player application and browser are two different programs/applications(or multiple programs) running at the same time.
There are two basic units of execution. processes and threads
Yes, it is.
Processes also known as programs or applications has its self-contained execution environment with its own memory space.
Process is considered to be heavyweight processes.
These are lightweight processes, has its execution environment , requires minimal resource to create than Process.
Threads are subset of process, each process has at least one thread and it shares process' memory and resources.
"main" thread. This thread can create additional threads.
ackage com.tutorials.threading; public class MainThread { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); } }
Each thread in java is an instance of the class java.lang.Thread.
When two threads trying to act on the same data, latest thread wins and the first thread update is lost.
Implement Runnable interface and its only method run(), which will have the code to be executed by the thread.
The object for the class that implements the Runnable interface is passed as an argument to the Thread constructor as explained below.
An application can use the Executor framework, in order to create a thread pool.
package com.tutorials.threading; class RunnableThread implements Runnable { @Override public void run() { System.out.println("This line is printed from a thread."); } } public class RunnableThreadExample { public static void main(String[] args) { // Runnable object is created RunnableThread myObject = new RunnableThread(); Thread myThreadObject = new Thread(myObject); myThreadObject.start(); } }
The class may extend Thread class since Thread class implements Runnable interface. The sub class run() method will provide its implementation and override Thread class method.
The thread run() method is invoked by creating object to the Extended Class and call start() method.
package com.tutorials.threading; public class ThreadExtended extends Thread { public void run() { System.out.println("The thread prints this line."); } public static void main(String args[]) { ThreadExtended myThreadObj = new ThreadExtended(); myThreadObj.start(); } }
Implementing the Runnable interface is used when your class need to extend another class. When you extend Thread class, you can not extend another class. so Implementing the Runnable interface is preferred.
Yes.
public void run() {}
Synchronization means allowing only one thread at a time to access an object.
Synchronization control the access the multiple threads to a shared resources. Without thread synchronization, one thread can modify a shared variable while another thread is working on the same variable, which leads to Thread Interference.
yes.
Yes. We need to handle java.lang.InterruptedException. The Sleeping thread throws InterruptedException when another thread intercepts its sleep.
No. It will throw IllegalThreadStateException during runtime. We need to create a new thread object and invoke start() method only once.
A thread may not be restarted once it has completed execution as it goes to dead state.
run() method can be called directly however it will not be executing the method under new thread instead the method gets run on current thread.
When start() method is called it invokes run() by create a new Thread.
package com.tutorials.threading; public class ThreadExtended extends Thread { public void run() { System.out.println(String.format("The thread %s execute this line.", Thread.currentThread().getName())); } public static void main(String args[]) { ThreadExtended myThreadObj = new ThreadExtended(); myThreadObj.run(); // called my main Thread myThreadObj.start(); // called my new Thread } }
package com.tutorials.threading; public class ConsumerProducerProblem { int value = 0; volatile boolean hasChanged = false; public void produce(int value) throws InterruptedException { while (hasChanged == true) { } System.out.println("Value set:" + value); this.value = value; hasChanged = true; } public void consume() throws InterruptedException { while (hasChanged == false) { } System.out.println(Thread.currentThread().getName() + " consumed value:" + value); hasChanged = false; } public static void main(String... s) { final ConsumerProducerProblem myObj = new ConsumerProducerProblem(); new Thread() { @Override public void run() { for (int i = 0; i <= 30; i++) { try { myObj.produce(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread("first consumer") { @Override public void run() { for (int i = 0; i <= 30; i++) { try { myObj.consume(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }
Thread.interrupted() | Thread.isInterrupted() |
interrupted() is a static method of Thread class and checks the current running thread if it is interrupted. | isInterrupted() is an instance method which checks the Thread object for its interrupt status that it is called on. |
Calling interrupted() clears/reset the interrupt status of the current thread. | calling isInterrupted() does not affect the status of the thread object. |
Thread.sleep(), Object.wait(), join().
This static method causes the current thread to suspend its execution for a specified period of time so that processor be available for the other threads of the application or yielding for other thread to complete.
sleep() method is overloaded and there are two versions.
public static void sleep(long miliseconds) throws InterruptedException public static void sleep(long miliseconds, int nanosecond) throws InterruptedException
try { while (true) { Thread.sleep(2000); } } catch (InterruptedException swallowedTheException) { /* BAD PRACTICE */ }
Instead re-interrupt the thread by calling interrupt() method. Because when the sleep() blocking method sniffs an interruption and throws InterruptedException, it clears the interrupted status.
try { while (true) { Thread.sleep(2000); } } catch (InterruptedException notSwallowedTheException) { // Restore the interrupted status Thread.currentThread().interrupt(); }
We may add check as explained below.
if (Thread.interrupted()) { return; }
An Instance method of a thread object.
It pauses the current thread execution in which the statement is called until the thread object on which join method is invoked complete its execution.
Consider an example Without using join().
package com.tutorials.threading; public class ThreadJoinExample extends Thread { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); return; } System.out.println("The Thread " + currentThread().getName() + " is completed now."); } public static void main(String[] args) { ThreadJoinExample myThread = new ThreadJoinExample(); myThread.start(); System.out.println(currentThread().getName() + " executes this line and completed now."); } }
Output:
main thread executes this line and completes now.
The Thread Thread-0 is completed now.
The main Thread of this program prints "main thread executes this line and completes now." and completes its execution before the myThread print "The Thread Thread-0 is completed now" and completes its execution.
To have the "main" thread wait for myThread object's thread to complete, we may call myThread.join() from the main Thread.
package com.tutorials.threading; public class ThreadJoinFromMainExample extends Thread { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); return; } System.out.println("The Thread " + currentThread().getName() + " is completed now."); } public static void main(String[] args) throws InterruptedException { ThreadJoinExample myThread = new ThreadJoinExample(); myThread.start(); System.out.println(currentThread().getName() + " is going to wait for myThread to complete."); myThread.join(); System.out .println(currentThread().getName() + " thread executes this line after myThread completed and main exits now."); } }
Output:
main is going to wait for myThread to complete.
The Thread Thread-0 is completed now.
main thread executes this line after myThread completed and main exits now.
Yes.
public final void join()
pause for the invoking thread object to complete.
public final synchronized void join (long milliSeconds)
pause for the invoking thread object to complete or resume after the specified milliseconds.
public final synchronized void join (long milliSeconds, int nano)
pause for the invoking thread object to complete or resume after the specified milliseconds plus nano.
indicates that the object has to stop doing what it does by calling interrupt() on the thread object.
When it receives an interrupt, it returns from the run() method .
package com.tutorials.threading; public class HandleInterruptedException { public static void main(String[] args) { String changeColors[] = { "BLUE", "YELLOW", "ORANGE", "WHITE", "BLACK" }; for (int i = 0; i < changeColors.length; i++) { // Pause for 5 seconds try { Thread.sleep(2000); if (i == 1) Thread.currentThread().interrupt(); } catch (InterruptedException e) { System.out.println("Interrupted . lets skip the color." + e); continue; } // Print color System.out.println(changeColors[i]); } } }
Output:
YELLOW
Interrupted. lets skip the color.java.lang.InterruptedException: sleep interrupted
WHITE
BLACK
When it iterates through colors array and at index 1,(YELLOW) the interrupt() is called on the executing thread (which becomes active after sleep), when it iterates through index 2, (ORANGE) sleep does not run because it is interrupted so it skips printing ORANGE.
package com.tutorials.threading; public class WaitForMSToJoinExample implements Runnable { public static void main(String[] args) throws InterruptedException { WaitForMSToJoinExample myObj = new WaitForMSToJoinExample(); Thread MyThreadObj = new Thread(myObj, "Child Thread"); MyThreadObj.start(); System.out.println("Main thread will wait for the other thread."); MyThreadObj.join(2000); System.out.println("Main thread exited after 2 sec."); } @Override public void run() { try { Thread.sleep(5000); System.out.println(Thread.currentThread().getName() + " completed now."); } catch (InterruptedException e) { e.printStackTrace(); } } }
Output:
Main thread will wait for the other thread.
Main thread exited after 2 sec.
Child Thread completed now.
In the above example, the main thread waited 2 seconds for other thread to complete, however main thread resumed its execution after 2 sec even though the other thread has not completed its execution.
We may add check as explained below.
if (Thread.interrupted()) { throw new InterruptedException(); }
The internal flag "interrupt status" tracks the status. Thread.interrupt() sets this flag and this flag is reset when Thread.interrupted (static) method is invoked to check the interruption status.
The non-static isInterrupted method, which queries the interrup status of another, does not change the interrupt status flag.
Also once the InterruptedException is thrown, the status is cleared.
No.
Although both methods pause the execution of the currently running thread, sleep() is meant for suspending the execution for short pause as it does not release the lock, while wait() is a conditional wait and it releases lock which can be acquired by another thread to change the condition on which it is waiting.
No. Neither increment operator (++) nor the decrement operaor (--) is thread safe.
For example, the statement i++ is not atomic. It involves multiple instructions that includes reading the value of i variable, increment its value by 1 and store the new i value to the variable.
When a thread is not granted CPU time because other threads were using it all, it is called starvation. The thread starves to death because other threads are using the CPU time instead of it.
No. Invoking the interrupt() method in a thread only triggers InterruptedException while that thread executing a method that throws InterruptedException.
A thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result.
It is a recursive situation where two or more threads would keep repeating a particular code logic. The intended logic is typically giving opportunity to the other threads to proceed in favor of current thread.
A real-world example of livelock occurs when two people meet in a narrow corridor, and each tries to be polite by moving aside to let the other pass, but they end up blocking each other from side to side without making any progress because they both repeatedly move the same way at the same time.
Race conditions occurs when 2 or more threads operate on same object without proper synchronization and the steps on the operation interleaves on other thread.
An example of Race condition is incrementing a counter since increment is not an atomic operation and can be further divided into three steps like read, update and write. If two threads tries to increment count at same time and if they read same value because of interleaving of read operation of one thread to update operation of another thread, one count will be lost when one thread overwrite increment done by other thread. atomic operations are not subject to race conditions because those operation cannot be interleaved.
Threads with high priority takes up all CPU time from threads with lower priority.
Threads are blocked indefinitely waiting to enter a synchronized block.
Threads waiting on an object by calling wait() and remain waiting indefinitely.
A deadlock is a state in which each member of a group of actions, is waiting for some other member to release a lock.
A livelock is similar to a deadlock, except that the states of the processes involved in the livelock constantly change with regard to one another however none progressing. Livelock is a special case of resource starvation; the general definition only states that a specific process is not progressing.
Slipped conditions represents that from the time a thread has checked a certain condition until it acts upon it, the condition has been changed by another thread so that it is erroneous for the first thread to act.
Synchronization is internally controlled by an entity known as the intrinsic lock or monitor lock. Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state to one thread and preventing access to other threads and establishing happens-before relationships that are essential to visibility.
Every object has an associated intrinsic lock. A thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when done.As long as a thread owns an intrinsic lock, no other thread can acquire the same lock, the other thread will block.
Guarded block is a mechanism of coordinating the execution of multiple threads in a multithreaded environment. Guarded block keeps checking for a particular condition to become true and only in that case the actual execution of the thread resumes.
Guarded blocks are of 2 types, synchronized guarded block and non-synchronized guarded block.
In synchronized guarded block, if the condition is false then the synchronized block simply calls the Object.wait() method to release the acquired monitor on that object and leaves the CPU to be used by other thread.
public synchronized void guardedBlockExample() { while(!sharedFlag) { try { wait(); } catch (InterruptedException e) {} } System.out.print("Shared flag is ON. The execution will continue now!"); }
In non-synchronized guarded block, execution is controlled to keep executing a blank loop until the condition becomes true. This approach has an obvious disadvantage of wasting the precious CPU time, which could have been better utilized by some other threads.
public void guardedBlockExample() { while(!sharedFlag) { // empty loop that breaks when condition is true. } System.out.println("Shared Flag is ON. Resuming execution."); }
A thread is said to be in BLOCKED state when it waits to acquire a object's monitor.
A thread can be in one of the following states:
NEW: A thread that has not yet started is in this state.
RUNNABLE: A thread executing in the Java virtual machine is in this state.
BLOCKED: A thread that is blocked waiting for a monitor lock is in this state.
WAITING: A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING: A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED: A thread that has exited is in this state.
A thread gets to wait state once it calls wait() on an Object. This is called Waiting State. Once a thread attains waiting state, it will continue to wait till some other thread notify() or notifyAll() on the object.
Once this thread is notified, it will not be runnable. It might be that other threads are also notified (using notifyAll()) or the first thread has not finished his work, so it is still blocked till it gets its chance. This is called Blocked State.
Once other threads have left and this thread gets chance, it moves to Runnable state after that it is eligible pick up work based on JVM threading mechanism and moves to run state.
Synchronization in Java is basically an implementation of monitors. When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method, the monitor belongs to the class.
A synchronized method acquires a monitor before it executes. For a class (static) method, the monitor associated with the Class object for the methods class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
Synchronized blocks in Java are reentrant. This means, that if a Java thread enters a synchronized block of code, and thereby take the lock on the monitor object the block is synchronized on, the thread can enter other Java code block synchronized on the same monitor object.
A thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization.
java.util. concurrent.locks ReentrantLock is a concrete implementation of Lock interface provided in Java concurrency package introduced in Java 1.5. ReentrantLock is a mutual exclusive lock with extended feature like fairness, which can be used to provide lock to longest waiting thread. ReentrantLock is similar to implicit locking provided by synchronized keyword in Java.
ReentrantLock allows the threads to enter into lock more than one time even if the thread is already holding lock. When first time thread enters into lock, hold count is set to one. Before unlock thread can re-enter into lock again and every time hold count is incremented by one. For every unlock request, hold count is decremented by one and when hold count is 0, it is unlocked.
Yes. A thread can have more than one lock.
synchronized (obj1) { synchronized (obj2) { //some code... } }
A synchronized method uses the method receiver as a lock, 'this' for non static methods and the enclosing class for static methods. Synchronized blocks uses the expression as a lock.
A synchronized method locks on the object instance the method is contained in while a synchronized block can lock on ANY object.
For synchronized methods, the lock will be held throughout the method scope, while in the synchronized block, the lock is held only during that block scope also known as critical section.
Synchronized block can throw NullPointerException if the expression provided as parameter evaluates to null, which is not the case with synchronized methods.
Synchronized block provides granular control over lock, as you can use any lock to provide mutual exclusion to critical section code. Synchronized method always lock either on current object or class level lock, if its static synchronized method.
Runnable represents a task in Java which is executed by Thread. java.lang.Runnable is an interface that defines only one method called run(). When a Thread is started in Java by using Thread.start() method it calls and execute the run() method of Runnable task which was passed to Thread when created.
when a program calls start() method, a new thread will be created and code inside run() method is executed in newly created thread whereas if the program calls run() method directly no new Thread be created and code inside run() will execute on current Thread itself.
A critical section represents a section of code or a block that is executed by multiple threads at the same time and where the sequence of execution of the threads makes a difference in the result of the concurrent execution of the critical section.
This run-time exception is thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
It is mandatory that a thread cannot call wait(), notify() or notifyAll() without holding the lock on the object the method is called on. Usually both the waiting or notifying threads call wait() and notify() from within a synchronized block or method.
The thread on WAIT state on an object wakes up for no reason, it is neither notified, timed out nor interrupted.For some reasons it is possible for a thread to wake up even if notify() and notifyAll() has not been called. This behavior is known as spurious wakeups, Wakeups without any reason.
Daemon thread in Java are those thread which runs in background and mostly created by JVM for performing background task. A daemon thread is a thread that does not prevent the JVM from exiting when the Java program finishes but the thread is still running. An example for a daemon thread is the garbage collection.
The setDaemon(boolean) method can be used to change the Thread daemon properties before the thread starts.
JVM doesn't wait for any daemon thread to finish the Java program before exiting while JVM waits for all the non-daemon thread to complete before exiting the Java program.
When JVM terminates, it doesn't not invoke the daemon thread's finally block or unwind the stack. However it is not the case with non-daemon threads.
A wait can be "woken up" by another thread calling notify on the monitor which is being waited on whereas a sleep cannot.
A wait (and notify) must happen in a block synchronized on the monitor object whereas sleep does not.
You call wait on Object itself whereas you call sleep on Thread.
While sleeping a Thread does not release the locks it holds, while waiting releases the lock on the object that wait() is called on.
Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.
An application can be concurrent when multiple tasks are performed simultaneously with shared resources.
An application is parallel when a single task is divided into multiple simple independent tasks which can be performed simultaneously.
The Object class in Java has 3 final methods that allow threads to communicate about the locked status of a resource.
wait() instructs the calling thread to release the lock and go to sleep until some other thread enters the same monitor and calls notify(). The wait() method releases the lock prior to waiting and reacquires the lock prior to returning from the wait() method. It is a native method.
synchronized( monitorObj ) { while( ! condition ) { monitorObj.wait(); } //critical section code }
notify() wakes up one single thread that called wait() on the same object. It should be noted that calling notify() does not actually give up a lock on a resource. It tells a waiting thread that that thread can wake up.
synchronized(monitorObj) { //Condition to invoke notify monitorObj.notify(); //additional code (optional) }
notifyAll() wakes up all the threads that called wait() on the same object. The highest priority thread will run first in most of the situation, though not guaranteed.
synchronized(monitorObj) { //Condition to invoke notify monitorObj.notifyAll(); //additional code (optional) }
No. A thread cannot wait on more than one object at a time.
The wait() and notify() methods are object specific and invoke on the object. The wait() method suspends the current thread of execution, and instructs the object to keep track of the suspended thread. The notify() method tells the object to wake up the suspended threads that it is currently keeping track of.
Official Definition is as follows: Mutexes are typically used to serialize access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section.
Mutex stands for Mutually Exclusive Semaphore.
As an example, hotel management has a key to each room. One customer can have the key, use the room, at the time. When he checks out, the hotel management gives (frees) the key to the next customer in the queue.
The Official Definition is as follows: A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore).
Mutex is basically mutual exclusion. Only one thread can acquire the resource at once and others wait. Semaphore is used to control the number of threads executing. There will be fixed set of resources. When the semaphore count reaches 0 then no other threads are allowed to acquire the resource. The threads get blocked till other threads owning resource releases. Mutex is just one thread while Semaphore is defined number of 'N' threads.
A mutex does have the concept of ownership while Semaphore doesn't, any thread can release a semaphore.
Mutexes may also support priority inheritance and recursion.
When a thread calls notify on some monitor, it wakes up a single thread that's waiting on that monitor, but which thread gets woken is decided by the scheduler. Unlike notify, interruption targets a specific thread and interruption does not require that the interrupted thread be waiting on a monitor.
Interruption is used only for cancellation while notify helps the waiting thread to attain it goal it is waiting for and help it continue its execution.
The key difference between notify and notifyAll is that notify() will cause only one thread to wake up while notifyAll method will make all the wating thread to wake up.
When a thread calls notify on some monitor, it wakes up a single thread that's waiting on that monitor, but which thread gets woken is decided by the scheduler. A thread can call notifyAll, which wakes up all the threads waiting for that monitor, then they all contend for the monitor, then the one thread get the monitor and others go back to waiting.
The monitor is released only after completing the remaining statements of the synchronized code even after the thread calls notify or notifyAll on the object.
A ReentrantLock is unstructured and flexible compared to the synchronized constructs. We don't need to use a block structure for locking and can even hold a lock across methods.
private ReentrantLock lock; public void method1() { ... lock.lock(); ... } public void method2() { ... lock.unlock(); ... }
Also ReentrantLock supports lock polling and interruptible lock waits that supports time-out. ReentrantLock also has support for configurable fairness policy, allowing more flexible thread scheduling.
A concurrent application's ability to execute in a timely manner is known as its liveness. The liveness problems include deadlock, starvation and livelock.
Threads can communicate with each other by using wait(), notify() and notifyAll() methods.
Volatile keyword is used on the variables and not on method while synchronized keyword is applied on methods and blocks not on variables.
Volatile does not acquire any lock on variable or object, but synchronized statement acquires lock on method or block in which it is used.
Volatile does not cause liveness problems such as dedlock while synchronized May cause as it acquires lock.
Volatile usually do not cause performance issues while synchronized block may cause performance issues.
Every thread has a priority, usually threads with higher priority gets precedence in execution but it depends on Thread scheduler. We can specify the priority of thread but it doesn't guarantee that higher priority thread will get executed before lower priority thread.
Thread priority is an int whose value varies from 1 to 10 where 1 is the lowest priority thread and 10 is the highest priority thread.Thread class also defines 3 constants. Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.
threadObj.setPriority(Thread.MIN_PRIORITY);
Thread Scheduler is the service that allocates the CPU time to the available runnable threads. Once a thread is created and started, it?s execution rely on the implementation of Thread Scheduler. Thread scheduler is OS dependent.
Time Slicing is the process to split the available CPU time to the available runnable threads. Allocation of CPU time to threads can be based on thread priority or the longest waiting thread will gets priority.
Context Switching is the process of storing and restoring of CPU state so that the thread execution can be resumed from the same point at a later point of time.
Context Switching is an essential feature for multitasking and for multi-threaded environment.
Synchronized block is preferred as it provides more granular control. It only locks the critical section of the code and that eliminates unnecessary object locking.
Every Object is associated with a monitor, only one thread can hold the monitor at a time. Acquiring the object monitor allow thread to hold lock on object. These methods are not called on the thread as it does not have its own lock.
As the monitor is with the object, wait is called on the object to have the thread move to wait state on that object. Similarly notify/notifyAll is called on the object to notify the waiting thread(s).
ThreadGroup is a class that provides information about a thread group. It helps to get the list of active threads in a thread group and to set the uncaught exception handler for the thread.
Ever since setUncaughtExceptionHandler (UncaughtExceptionHandler e) was added in Java 1.5, it serves the purpose to set exception handler and ThreadGroup becomes obsolete and no longer used.
The java.lang.Thread. setUncaughtExceptionHandler() method sets the handler to be invoked when this thread abruptly terminates due to an uncaught exception.
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
This method does not return any thing.
public class ExceptionHandlerEx { static class MyThreadClass implements Runnable { public void run() { throw new NullPointerException(); } } public static void main(String[] args) { Thread t = new Thread(new MyThreadClass()); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { System.out.println(t + " throws exception: " + e); } }); t.start(); } }
A thread dump is a snapshot of the state of all threads that are part of the process. The state of each thread is presented with a stack trace, which shows the contents of a thread's stack.
Some of the threads belong to the Java application you are running, while others are JVM internal threads.
Profiler, Kill -3 command and jstack tool can be used to generate thread dump. jstack tool is bundles with JDK installation and it is a command line tool.
The jstack command-line utility attaches to the specified process or core file and prints the stack traces of all threads that are attached to the virtual machine, including Java threads and VM internal threads, and optionally native stack frames. The utility also performs deadlock detection.
A stack trace of all threads can be useful in diagnosing a number of issues, such as deadlocks or hangs.
We may analyse any deadlock by getting the thread dump and verifying the stack trace of the active threads. we may looks for the threads that are BLOCKED, the resource it is waiting for, the thread that is currently holding the lock from the stack trace.
Since JDK 1.5 there are some powerful methods added in the java.lang.management package to diagnose and detect deadlocks. The java.lang.management.ThreadMXBean interface is management interface for the thread system of the Java virtual machine. It has two methods which can leveraged to detect deadlock in a Java application.
findMonitorDeadlockedThreads() method detects cycles of threads that are in deadlock waiting to acquire object monitors and returns an array of thread IDs that are deadlocked waiting on monitor.
findDeadlockedThreads() method returns an array of thread IDs that are deadlocked waiting on monitor or ownable synchronizers.
Yes. we can avoid overriding run method while extending Thread class. The start method will execute the default implementation which has no action.
Java Thread pool is a group of worker threads that are waiting for the tasks to be assigned and be reused again. Worker threads return to the thread pool after it completes its task.
A group of fixed size threads are created in the thread pool. A thread from the thread pool is chosen and assigned a runnable task by the service provider. After completion of the job, thread is returns to the thread pool.
java.util.concurrent.Executors provide implementation of java.util.concurrent.Executor interface to create the thread pool in java.
Improves performance of multithreaded application as the thread pool eliminates the overhead of creating/recreating thread objects.
The java.util.concurrent. atomic package defines classes that support atomic operations on single variables. All classes have get and set methods to read and write similar to volatile variables.
import java.util.concurrent.atomic.AtomicInteger; public class AtomicCounter { private AtomicInteger i= new AtomicInteger(0); public void increment() { i.incrementAndGet(); } public void decrement() { i.decrementAndGet(); } public int value() { return i.get(); }
A lock is a thread synchronization mechanism like synchronized blocks that are sophisticated than Java's synchronized blocks. From Java 5 the package java.util.concurrent.locks contains several lock implementations.
The advantages of using locks are,
- implements fairness.
- possible to try to acquire the lock and backout immediately or after a timeout if the lock cannot be acquired.
- possible to acquire and release locks in different scopes in any order.
In preemptive scheduling, the thread with highest priority executes until it enters into the waiting or dead state.
Priority of daemon threads is always 1, the lowest priority. Thread scheduler schedules these threads only when CPU is idle.
yield() method gives a notice to the thread scheduler that the current thread is willing to yield its current use of a processor. The thread scheduler is free to ignore this hint.
No. If a object has synchronized instance methods then the Object itself is used a lock object for controlling the synchronization. Therefore all other instance methods need to wait until previous method call is completed.
Thread leak happens when an application does not release references to a thread object properly that prevents the thread from being garbage collected.
Thread leak can cause performance issues and application slowness, when too many threads gets created and not garbage collected after it attains the terminated state.
CountDownLatch is a synchronizer type which allows one Thread to wait for one or more Threads before starts processing.
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is not a reusable phenomenon, the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
package CountDownLatchExample; import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { static final CountDownLatch latch = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException { MyThread thread = new MyThread(latch); new Thread(thread).start(); new Thread(thread).start(); latch.await(); System.out.println(Thread.currentThread().getName() + " done."); } } class MyThread implements Runnable { CountDownLatch latch; MyThread(CountDownLatch latch) { this.latch = latch; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " completed."); latch.countDown(); } }
CountDownLatch works in latch principle, main thread will wait until gate is open. One thread waits for n number of threads specified while creating CountDownLatch in Java.
Classical example of using CountDownLatch in Java is any server side core Java application which uses services architecture, where multiple services are provided by multiple threads and application can not start processing until all services have started successfully.
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
A CyclicBarrier supports an optional Runnable command that is run once per barrier point, after the last thread in the party arrives, but before any threads are released. This barrier action is useful for updating shared-state before any of the parties continue.
CountDownLatch behavior could be achieved using low level constructs such as wait-notify, synchronized. CountDownLatch is built using such constructs only.
An object is considered immutable if its state cannot change after it is constructed. Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.
The below are the rules for creating an immutable class.
- Don't provide "setter" methods.
- Make all fields final and private.
- Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
- If the instance fields include references to mutable objects, don't allow those objects to be changed:
- Don't provide methods that modify the mutable objects.
- Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
You can find the ThreadLocal questions here.
Find the volatile related questions here.
The fork/join framework is an implementation of the ExecutorService interface that helps you deal with multiple processors. It is designed for tasks that can be broken into smaller subtasks recursively. The goal is to use all the available processing power to enhance the performance of your application.
Using any ExecutorService implementation, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct because it uses a work-stealing algorithm. Worker threads that run out of things to do can steal tasks from other threads that are still busy.
The core of the fork/join framework is the ForkJoinPool class, an extension of the AbstractExecutorService class. ForkJoinPool implements the core work-stealing algorithm and can execute ForkJoinTask processes.
Exchanger is a synchronization point at which threads can pair and swap elements between the pair. Each thread presents some object on entry to the exchange method, matches with a partner thread, and receives its partner's object on return.
An Exchanger may be viewed as a bidirectional form of a SynchronousQueue. Exchangers may be useful in applications such as genetic algorithms and pipeline designs.
package main.java.tags; import java.util.concurrent.*; import java.util.*; public class ExchangerExample { public static void main(String[] args) { Exchanger<Integer> exchanger = new Exchanger<Integer>(); Thread t1 = new MyThread(exchanger, new Integer(5)); Thread t2 = new MyThread(exchanger, new Integer(10)); t1.start(); t2.start(); } } class MyThread extends Thread { Exchanger<Integer> exchanger; Integer numberToExchange; MyThread(Exchanger<Integer> exchanger, Integer message) { this.exchanger = exchanger; this.numberToExchange = message; } public void run() { try { System.out.println(this.getName() + " has value: " + numberToExchange); // exchange messages numberToExchange = exchanger.exchange(numberToExchange); System.out.println("After exchange " + this.getName() + " has value: " + numberToExchange); } catch (Exception e) { } } }
The above example exchanges Integer objects between a pair of threads. The below is the output.
Thread-0 has value: 5 Thread-1 has value: 10 After exchange Thread-0 has value: 10 After exchange Thread-1 has value: 5
When a thread acquires a WriteLock, no other thread can acquire the ReadLock nor the WriteLock of the same instance of ReentrantReadWriteLock, unless that thread releases the lock. However, multiple threads can acquire the ReadLock at the same time.
When using any of the Lock implementation the lock is usually released in finally block. This ensures that if there is exception in method body, lock is released.
public void method() { reentrantLock.lock(); try { //perform task }finally { reentrantLock.unlock(); } }
- Non-blocking or optimistic attempt to acquire a lock using tryLock ,
- attempt to acquire the lock that can be interrupted using lockInterruptibly,
- attempt to acquire a lock that can timeout using tryLock(long time, TimeUnit unit),
- guaranteed ordering,
- and deadlock detection.
The Callable interface is similar to Runnable,both are designed for classes whose instances are potentially executed by another thread.
A Runnable, however, does not return a result and cannot throw a checked exception unlike Callable which returns a result and throw exceptions.
The interrupt flag or interrupt status, is an internal Thread flag that is set when the thread is interrupted. To set it, simply call thread.interrupt() on the thread object.
If a thread is currently inside one of the methods that throw InterruptedException (wait, join, sleep), then this method immediately throws InterruptedException.
FutureTask implements Future interface and provides asynchronous processing. It contains the methods to start and cancel a task and also methods that can return the state of the FutureTask as whether its completed or cancelled. We need a callable object to create a future task and then we can use Java Thread Pool Executor to process these asynchronously.
Memory-interference, race conditions, deadlock, livelock, and starvation are example of problems we encounter in multi-threading and concurrent programming.
You cannot perform any further action/callback on a Futures result without blocking since Future does not notify when completed. It provides get() method that blocks until the result is ready.
Multiple Future cannot be chained together, for example, the result of one Future cannot be sent to other Future.
Future does NOT provide Exception handling constructs.
Future cannot be manually marked ended/completed.
CompletableFuture achieves all the limitations in Future.
CompletableFuture implements Future and CompletionStage interfaces and provides a huge set of convenience methods for creating, chaining and combining multiple Futures. It also has a very comprehensive exception handling support.
Green threads refers to a model in which the Java virtual machine itself creates, manages, and context switches all Java threads within one operating system process. No operating system threads library is used. Green threads are in past, JVMs work only with native threads since 1.3.
Native threads refers to model in which the Java virtual machine creates and manages Java threads using the operating system threads library, for example, libThread in Unix and each Java thread is mapped to one threads library thread.
More multi threading and concurrency question can be found here.