The lifecycle of a thread in Java

Thread is a topic that can not be circumnavigated in Java. Today, this article will explain the life cycle of threads in Java in detail, hoping to give you some inspiration.

Status of Thread in Java

Thread has six states in Java, which are:

  1. NEW – The newly created Thread has not yet been executed
  2. RUNNABLE – RUNNABLE threads, both ready to run and running.
  3. BLOCKED – A thread that is waiting for a resource lock
  4. WAITING – WAITING indefinitely for another thread to perform a particular operation
  5. TIMED_WAITING – Waiting for another thread to perform a particular operation for a certain amount of time
  6. TERMINATED – The thread is TERMINATED

We can use a graph to visualize it:

The following is the definition in the JDK code:

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;
    }
Copy the code

NEW

NEW indicates that the thread has been created but has not yet started execution. Let’s look at an example of NEW:

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(a) {}}Copy the code

The above code will print:

NEW
Copy the code

Runnable

Runnable indicates that the thread is in the executable state. Including running and ready to run.

Why are they both called Runnable? We know that in a multitasking environment, there are only a limited number of cpus, so tasks are executed in a round-robin manner. The THREAD scheduler in the JVM allocates a specific execution time to each thread, and when the execution time is up, the thread scheduler frees the CPU for other Runnable threads to execute.

Let’s look at an example of Runnable:

public class RunnableThread implements Runnable {
    @Override
    public void run(a) {}public static void main(String[] args) {
        Runnable runnable = new RunnableThread();
        Thread t = newThread(runnable); t.start(); log.info(t.getState().toString()); }}Copy the code

The above code will print:

RUNNABLE
Copy the code

BLOCKED

BLOCKED indicates that a thread is waiting for a resource lock that is currently being held by another thread.

Let’s take an example:

public class BlockThread implements Runnable {
    @Override
    public void run(a) {
        loopResource();
    }

    public static synchronized void loopResource(a) {
        while(true) {
            // Infinite loop}}public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new BlockThread());
        Thread 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); }}Copy the code

In the above example, because T1 is an infinite loop, it will hold the resource lock all the time, causing T2 to be unable to obtain the resource lock and thus remain BLOCKED.

We get the following result:

12:40:11.710 [main] info.flydean.blockthread - RUNNABLE 12:40:11.713 [main] info.flydean.blockthread - RUNNABLE 12:40:11.713 [main] info.flydean.blockthread - RUNNABLE 12:40:11.713 [main] info.flydean.blockthread - BLOCKEDCopy the code

WAITING

WAITING indicates that a thread is WAITING for another thread to perform a specific operation. There are three ways to cause a thread to be in WAITTING state:

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

The 1,2 methods do not need to pass in time parameters.

Let’s look at an example of use:

public class WaitThread implements  Runnable{

    public static Thread t1;
    @Override
    public void run(a) {
        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(newWaitThread()); t1.start(); }}Copy the code

In this example, we call t2.join(), which makes the T1 thread calling it WAITTING.

Let’s look at the output:

12:44:12.958 [Thread-1] INFO com.flydean.WaitThread - t1 WAITING
12:44:12.964 [Thread-0] INFO com.flydean.WaitThread - t2 TERMINATED
Copy the code

TIMED_WAITING

The TIMED_WAITING state means that you are waiting for another thread to perform some specific operation for a finite amount of time.

There are five 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:

public class TimedWaitThread implements  Runnable{
    @Override
    public void run(a) {
        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()); }}Copy the code

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

Look at the output:

12:58:02. [the main] INFO 706 com. Flydean. TimedWaitThread - TIMED_WAITINGCopy the code

So, what’s the difference between TIMED_WAITING and WAITTING?

TIMED_WAITING if no specific operation is performed by another thread within a given period of time, the TIMED_WAITING will wake up and enter the queue for the resource lock. If the lock can be obtained, the TIMED_WAITING state will become Runnable, and if the lock cannot be obtained, it will become BLOCKED.

TERMINATED

TERMINATED indicates that the thread is TERMINATED. Let’s look at an example:

public class TerminatedThread implements Runnable{
    @Override
    public void run(a) {}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()); }}Copy the code

Output result:

13:02:38. [the main] INFO 868 com. Flydean. TerminatedThread - TERMINATEDCopy the code

Examples of this article can be found at github.com/ddean2009/l…

See flydean’s blog for more tutorials