Friday, 31 August 2018

Thread Life Cycle

The java.lang.Thread class contains a static State enum – which defines its potential states. During any given point of time, the thread can only be in one of these states:

NEW – newly created thread that has not yet started the execution

RUNNABLE – either running or ready for execution but it’s waiting for resource allocation

BLOCKED – waiting to acquire a monitor lock to enter or re-enter a synchronized block/method

WAITING – waiting for some other thread to perform a particular action without any time limit

TIMED_WAITING – waiting for some other thread to perform a specific action for a specified period

TERMINATED – has completed its execution

All these states are covered in the diagram above; let’s now discuss each of these in detail.

New

A NEWThread (or a Born Thread) is a thread that’s been created but not yet started. It remains in this state until we start it using the start() method.

The following code snippet shows a newly created thread that’s in the NEW state:

1

2

3

Runnable runnable = newNewState();

Thread t = newThread(runnable);

Log.info(t.getState());

Since we’ve not started the mentioned thread, the method t.getState() prints:

1

NEW

Runnable

When we’ve created a new thread and called the start() method on that, it’s moved from NEW to RUNNABLE state. Threads in this state are either running or ready to run, but they’re waiting for resource allocation from the system.

In a multi-threaded environment, the Thread-Scheduler (which is part of JVM) allocates a fixed amount of time to each thread. So it runs for a particular amount of time, then relinquishes the control to other RUNNABLE threads.

For example, let’s add t.start() method to our previous code and try to access its current state:

1

2

3

4

Runnable runnable = newNewState();

Thread t = newThread(runnable);

t.start();

Log.info(t.getState());

This code is most likely to return the output as:

1

RUNNABLE

Note that in this example, it’s not always guaranteed that by the time our control reaches t.getState(), it will be still in the RUNNABLE state.

It may happen that it was immediately scheduled by the Thread-Scheduler and may finish execution. In such cases, we may get a different output.

Blocked

A thread is in the BLOCKED state when it’s currently not eligible to run. It enters this state when it is waiting for a monitor lock and is trying to access a section of code that is locked by some other thread.

Let’s try to reproduce this state:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

publicclassBlockedState {

publicstaticvoidmain(String[] args) throwsInterruptedException {

Thread t1 = newThread(newDemoThreadB());

Thread t2 = newThread(newDemoThreadB());

t1.start();

t2.start();

Thread.sleep(1000);

Log.info(t2.getState());

System.exit(0);

}

}

classDemoThreadB implementsRunnable {

@Override

publicvoidrun() {

commonResource();

}

publicstaticsynchronizedvoidcommonResource() {

while(true) {

// Infinite loop to mimic heavy processing

// 't1' won't leave this method

// when 't2' try to enters this

}

}

}

In this code:

We’ve created two different threads – t1 and t2

t1 starts and enters the synchronized commonResource() method; this means that only one thread can access it; all other subsequent threads that try to access this method will be blocked from the further execution until the current one will finish the processing

When t1 enters this method, it is kept in infinite while loop; this is just to imitate heavy processing so that all other threads cannot enter this method

Now when we start t2, it tries to enter commonResource() method, which is already being accessed by t1, thus, t2 will be kept in BLOCKED state

Being in this state, we call t2.getState() and get the output as:

1

BLOCKED

Waiting

A thread is in WAITING state when it’s waiting for some other thread to perform a particular action.According to JavaDocs, any thread can enter this state by calling any one of following three methods:

object.wait()

thread.join() or

LockSupport.park()

Note that in wait() and join() – we do not define any timeout period as that scenario is covered in the next section.

We have a separate tutorial that discusses in detail the use of wait(), notify() and notifyAll().

For now, let’s try to reproduce this state:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

publicclassWaitingState implementsRunnable {

publicstaticThread t1;

publicstaticvoidmain(String[] args) {

t1 = newThread(newWaitingState());

t1.start();

}

publicvoidrun() {

Thread t2 = newThread(newDemoThreadWS());

t2.start();

try{

t2.join();

} catch(InterruptedException e) {

Thread.currentThread().interrupt();

Log.error("Thread interrupted", e);

}

}

}

classDemoThreadWS implementsRunnable {

publicvoidrun() {

try{

Thread.sleep(1000);

} catch(InterruptedException e) {

Thread.currentThread().interrupt();

Log.error("Thread interrupted", e);

}

Log.info(WaitingState.t1.getState());

}

}

Let’s discuss what we’re doing here:

We’ve created and started the t1

t1 creates a t2 and starts it

While the processing of t2 continues, we call t2.join(), this puts t1 in WAITING state until t2 has finished execution

Since t1 is waiting for t2 to complete, we’re calling t1.getState() from t2

The output here is, as you’d expect:

1

WAITING

Timed Waiting

A thread is in TIMED_WAITING state when it’s waiting for another thread to perform a particular action within a stipulated amount of time.