Thread life cycle in Java
New: A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread. It is also referred to as a born thread.
Runnable: After a newly born thread is started, the thread becomes runnable. A thread in this state is considered to be executing its task.
Waiting: Sometimes, a thread transitions to the waiting state while the thread waits for another thread to perform a task.A thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
Timed waiting: A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
Terminated ( Dead ): A runnable thread enters the terminated state when it completes its task or otherwise terminates.
Thread Creation
To run tasks simultaneously, each of these tasks will run in a separate thread. To define a "task", we create an instance of Runnable. Then we will wrap each of these Runnables around a Thread object.
Method 1: Create Thread by Implementing Runnable Interface
Step 1: public void run(
- implement a run() method provided by Runnable interface.
- This method provides entry point for the thread and you will put you complete business logic inside this method.
Step 2:
Thread(Runnable threadObj, String threadName);
- instantiate a Thread object
- threadObj is an instance of a class that implements the Runnable interface and threadName is the name given to the new thread.
Step 3:
void start();
- Once Thread object is created, you can start it by calling
start()
method, which executes a call torun()
method.
Method 2: Create Thread by Extending Thread Class
This approach provides more flexibility in handling multiple threads created using available methods in Thread class.
Step 1: public void run()
- override
run()
method available in Thread class Step 2:void start();
- Once Thread object is created, you can start it by calling
start()
method
Thread Synchronization
- Synchronize is implemented using a concept called monitors.
- Each object in Java is associated with a monitor, which a thread can lock or unlock.
- Only one thread at a time may hold a lock on a monitor.
synchronized(objectidentifier) {
// Access shared variables and other shared resources
}
objectidentifier
is a reference to an object whose lock associates with the monitor that the synchronized statement represents.
Inter-thread Communication
Inter thread communication is important when you develop an application where two or more threads exchange some information. ||| |---|---| public void wait() | Causes the current thread to wait until another thread invokes the notify(). public void notify()| Wakes up a single thread that is waiting on this object's monitor.| public void notifyAll()|Wakes up all the threads that called wait( ) on the same object.
- These methods have been implemented as final methods in Object, so they are available in all the classes.
- All three methods can be called only from within a synchronized context.
Thread-safety with the Java final keyword
- Essentially,
final
can be used to make sure that when you construct an object, another thread accessing that object doesn't see that object in a partially-constructed state, as could otherwise happen.- This is because when used as an attribute on the variables of an object, final has the following important characteristic as part of its definition:
When the constructor exits, the values of final fields are guaranteed to be visible to other threads accessing the constructed object.
- This is because when used as an attribute on the variables of an object, final has the following important characteristic as part of its definition:
Final object references
- The fields on any object accessed via a final reference are also guaranteed to be at least as up to date as when the constructor exits.
This means that: Values of final fields, including objects inside collections referred to by a final reference, can be safely read without synchronization.
- immutable objects (ones where all fields are final and are either primitives or references to immutable objects) can be concurrently accessed without synchronization.
- It is also safe to read "effectively immutable" objects (ones whose fields aren't actually final, but in practice never change) via a final reference.
It's important to emphasise that storing a reference to an object in a final field only makes the reference immutable, not the actual object.
Thread Priorities:
- Every Java thread has a priority that helps the operating system determine the order in which threads are scheduled.
- In the range between
MIN_PRIORITY
(a constant of 1) andMAX_PRIORITY
(a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5). - Thread priorities cannot guarantee the order in which threads execute and very much platform dependent.
- Thread object encapsulates many details, such as a thread's priority.