Introduction

Threads is a frequently used technology in java, this article will explain in detail the life cycle of threads in java, I hope you can give some help.

The state of Thread in java

There are six states of Thread in java, which are.

  1. NEW - newly created Thread, has not yet started execution
  2. RUNNABLE - Thread in runnable state, including ready to run and running.
  3. BLOCKED - Threads that are waiting for a resource lock
  4. WAITING - A thread that is waiting indefinitely for other threads to perform a specific operation
  5. TIMED_WAITING - Waiting for a certain amount of time for other threads to perform a specific operation
  6. TERMINATED - the thread has finished executing

We can visualize this in a diagram.

states of Thread

The definition in the JDK code is as follows.

 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

NEW

NEW means that the thread is created, but has not yet started execution. Let’s look at an example of NEW.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class NewThread implements Runnable{
    public static void main(String[] args) {
        Runnable runnable = new NewThread();
        Thread t = new Thread(runnable);
        log.info(t.getState().toString());
    }

    @Override
    public void run() {

    }
}

The above code will output.

1
NEW

Runnable

Runnable indicates that a thread is in an executable state. This includes both running and ready to run.

Why are both of them called Runnable? We know that in a multitasking environment, the number of CPUs is limited, so tasks are processed by rotating CPUs. The thread scheduler in the JVM allocates a specific execution time for each thread, and when the execution time is over, the thread scheduler will release the CPU for other Runnable threads.

Let’s look at an example of Runnable.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class RunnableThread implements Runnable {
    @Override
    public void run() {

    }

    public static void main(String[] args) {
        Runnable runnable = new RunnableThread();
        Thread t = new Thread(runnable);
        t.start();
        log.info(t.getState().toString());
    }
}

The above code will output.

1
RUNNABLE

BLOCKED

BLOCKED means that the thread is waiting for a resource lock and the resource is currently occupied by another thread.

Let’s take an example.

 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
public class BlockThread implements Runnable {
    @Override
    public void run() {
        loopResource();
    }

    public static synchronized void loopResource() {
        while(true) {
            //infinite loop
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new BlockThread());
        Thread t2 = new Thread(new BlockThread()). t2 = new Thread(new BlockThread());

        t1.start();
        t2.start();

        Thread.sleep(1000);
        log.info(t1.getState().toString());
        log.info(t2.getState().toString());
        System.exit(0);
    }
}

In the above example, since t1 is an infinite loop, it will keep occupying the resource lock, causing t2 to be unable to get the resource lock and thus be in the BLOCKED state.

We will get the following result.

1
2
12:40:11.710 [main] INFO com.javaisland.BlockThread - RUNNABLE
12:40:11.713 [main] INFO com.javaisland.BlockThread - BLOCKED

WAITING

The WAITING state means that a thread is waiting for another thread to perform a specific action. There are three ways to cause a thread to be in the WAITTING state.

  1. object.wait()
  2. thread.join()
  3. lockSupport.park()

Methods 1 and 2 do not require a time parameter to be passed.

Let’s look at the following example of use.

 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
public class WaitThread implements  Runnable{

    public static Thread t1;
    @Override
    public void run() {
        Thread t2 = new Thread(()->{
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("Thread interrupted", e);
            }
            log.info("t1"+t1.getState().toString());
        });
        t2.start();

        try {
            t2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted", e);
        }
        log.info("t2"+t2.getState().toString());
    }

    public static void main(String[] args) {
        t1 = new Thread(new WaitThread());
        t1.start();

    }
}

In this example, we are calling t2.join(), which will cause the t1 thread that called it to be in the WAITTING state.

Let’s look at the output.

1
2
12:44:12.958 [Thread-1] INFO com.javaisland.WaitThread - t1 WAITING
12:44:12.964 [Thread-0] INFO com.javaisland.WaitThread - t2 TERMINATED

TIMED_WAITING

The TIMED_WAITING state means waiting for a limited time for other threads to perform certain operations.

There are 5 ways to achieve this state in java.

  1. thread.sleep(long millis)
  2. wait(int timeout) or wait(int timeout, int nanos)
  3. thread.join(long millis)
  4. lockSupport.parkNanos
  5. lockSupport.parkUntil

Let’s take an example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TimedWaitThread implements Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Thread interrupted", e);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TimedWaitThread obj1 = new TimedWaitThread();
        Thread t1 = new Thread(obj1);
        t1.start();

        // The following sleep will give enough time for ThreadScheduler
        // to start processing of thread t1
        Thread.sleep(1000);
        log.info(t1.getState().toString());
    }
}

In the above example we have called Thread.sleep(5000) to keep the thread in TIMED_WAITING state.

Look at the following output.

1
12:58:02.706 [main] INFO com.javaisland.TimedWaitThread - TIMED_WAITING

So the question arises, what is the difference between TIMED_WAITING and WAITTING?

TIMED_WAITING will be woken up if it doesn’t wait for a specific operation by another thread within a given time, thus entering the queue of contention for resource locks, and will become Runnable if it can get a lock, or BLOCKED if it can’t.

TERMINATED

TERMINATED means that the thread has finished executing. Let’s look at the following example.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class TerminatedThread implements Runnable{
    @Override
    public void run() {

    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new TerminatedThread());
        t1.start();
        // The following sleep method will give enough time for
        // thread t1 to complete
        Thread.sleep(1000);
        log.info(t1.getState().toString());
    }
}

Output result.

1
13:02:38.868 [main] INFO com.javaisland.TerminatedThread - TERMINATED