Java线程状态

Java的线程状态定义在Thread.State枚举里,源码如下:

public enum State {

    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
    
}

源码显示总共有六种线程状态:

状态 解释
NEW 新建状态
RUNNABLE 可运行状态
BLOCKED 阻塞状态
WAITING 等待状态
TIMED_WAITING 限时等待状态(即时间一到跳出等待)
TERMINATED 终止状态(被中断或正常结束)

线程的状态切换总体上如下:

  • 新建—>可运行—>(阻塞、等待、限时等待)—>可运行—>终止

括号中的状态可有可无,看代码中的具体操作,而新建、可运行、终止状态是线程必然会经历的状态。“新建”和“终止”状态分别为起始和结束状态,这两种状态和“可运行”状态之间的关系是不可逆的。其他状态均能和“可运行”状态相互转换。

代码展示不同的线程状态的切换:

1.NEW->RUNNABLE->TERMINATED

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description NEW->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRT {

    public static void main(String[] args) {

        Thread thread=new Thread(ThreadStateNRT::printThreadStatus);
        log.info(thread.getName()+ ":" + thread.getState());
        thread.start();
        //等待线程执行完毕。
        try {
            thread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        log.info(thread.getName()+ ":" + thread.getState());

    }

    private static void printThreadStatus() {
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
    }

}

运行打印结果如下:

18:01:55.558 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:NEW
18:01:55.562 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:RUNNABLE
18:01:55.562 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:TERMINATED

2.NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRBRT {

    //锁
    private static final Object lock=new Object();
    //锁定标志
    private static volatile boolean lockFlag=true;
    //执行顺序
    private static volatile int order=0;


    public static void main(String[] args) {
        //辅助线程,制造synchronized状态。
        Thread assistantThread = new Thread(ThreadStateNRBRT::run1);
        assistantThread.start();
        try {
            //保证assistantThread先执行。
            Thread.sleep(10);
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        Thread showThread = new Thread(ThreadStateNRBRT::run2);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());
        //因为无法判断显示线程何时执行,所以循环直到显示线程执行。
        while (true){
            if(showThread.getState()==Thread.State.BLOCKED){
                log.info(showThread.getName()+ ":" + Thread.State.BLOCKED);
                lockFlag=false;
                break;
            }
        }
        //等待两个线程执行完毕。
        try {
            assistantThread.join();
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run1() {
        int i = 0 ;
        while (i < 1000) {
            //保证先进入同步范围。
            if (order == 0) {
                //锁定一定时间
                synchronized (lock){
                    //启动另一个同步
                    order=1;
                    while (lockFlag) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            log.error(e.getMessage(),e);
                            Thread.currentThread().interrupt();
                        }
                    }
                }
            }
            i++;
        }

    }

    private static void run2() {
        int i = 0;
        while (i < 1000) {
            //保证后进入同步范围。
            if (order == 1) {
                synchronized (lock){
                    log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
                }
                break;
            }
            i++;
        }
    }

}

运行结果如下:

18:04:49.345 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:NEW
18:04:49.349 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:RUNNABLE
18:04:49.349 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:BLOCKED
18:04:50.335 [Thread-1] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:RUNNABLE
18:04:50.335 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:TERMINATED

3.NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
能造成WAITING状态的行为有多种:

方法 运用
wait() 同步代码块/方法中调用锁对象的wait()方法
join() 线程对象调用join()方法
park() 直接调用LockSupport的静态方法park()
lock() 调用Lock实现类的对象的lock()方法
await() 调用Condition实现类的对象的await()

下面展示当中的一些场景:
1.wait()

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRWRT {

    //锁
    private static final Object lock=new Object();

    public static void main(String[] args) {
        //展示线程
        Thread showThread = new Thread(ThreadStateNRWRT::run);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());
        //循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
        while (true){
            if(showThread.getState()==Thread.State.WAITING){
                log.info(showThread.getName()+ ":" + showThread.getState());
                break;
            }
        }
        synchronized (lock){
            lock.notifyAll();
        }


        try {
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }


    private static void run() {
        //等待
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        synchronized (lock){
            try {
                lock.wait();
            } catch (InterruptedException e) {
                log.error(e.getMessage(),e);
                Thread.currentThread().interrupt();
            }
        }
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
    }

}

运行结果为:

18:49:17.933 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:NEW
18:49:17.936 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:RUNNABLE
18:49:18.942 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:WAITING
18:49:18.942 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:RUNNABLE
18:49:18.942 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:TERMINATED

2.lock()

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRWRTLock {

    //锁
    private  static Lock lock=new ReentrantLock();
    //锁定标志
    private static volatile boolean lockFlag=true;
    //执行顺序
    private static volatile int order=0;

    public static void main(String[] args) {

        //展示线程
        Thread showThread = new Thread(ThreadStateNRWRTLock::run1);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());
        //辅助线程,制造synchronized状态。
        Thread assistantThread = new Thread(ThreadStateNRWRTLock::run2);
        assistantThread.start();
        //循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程退出同步。
        while (true){
            if(showThread.getState()==Thread.State.WAITING){
                log.info(showThread.getName()+ ":" + showThread.getState());
                lockFlag=false;
                break;
            }
        }
        try {
            showThread.join();
            assistantThread.join();
        } catch (InterruptedException e) {
            log.trace(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run2() {
        while (true) {
            //保证先进入同步范围。
            if (order == 0) {
                //加锁
                lock.lock();
                try {
                    order=1;
                    while (lockFlag) {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            log.error(e.getMessage(),e);
                            Thread.currentThread().interrupt();
                        }
                    }
                }finally {
                    lock.unlock();
                }
                break;
            }
        }
    }

    private static void run1() {
        while (true){
            //保证后进入同步范围。
            if (order==1){
                lock.lock();
                try{
                    log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
                }finally {
                    lock.unlock();
                }
                break;
            }
        }
    }
}

运行结果为:

18:51:27.696 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:NEW
18:51:27.700 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:RUNNABLE
18:51:27.701 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:WAITING
18:51:27.711 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:RUNNABLE
18:51:27.711 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:TERMINATED

3.await()

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRWRTCondition {

    //锁
    private static Lock lock=new ReentrantLock();
    private static Condition condition=lock.newCondition();

    public static void main(String[] args) {

        //展示线程
        Thread showThread = new Thread(ThreadStateNRWRTCondition::run);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());

        //循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
        while (true){
            if(showThread.getState()==Thread.State.WAITING){
                log.info(showThread.getName()+ ":" + showThread.getState());
                break;
            }
        }

        lock.lock();
        try{
            condition.signal();
        }finally {
            lock.unlock();
        }


        try {
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run() {
        //等待
        lock.lock();
        try{
            try {
                condition.await();
            } catch (InterruptedException e) {
                log.error(e.getMessage(),e);
                Thread.currentThread().interrupt();
            }
        }finally {
            lock.unlock();
        }
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
    }

}

运行结果为:

18:53:13.367 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:NEW
18:53:13.370 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:RUNNABLE
18:53:13.370 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:WAITING
18:53:13.371 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:RUNNABLE
18:53:13.371 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:TERMINATED

4.park()

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

/**
 * @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRWRTLockSupport {

    public static void main(String[] args) {

        //展示线程
        Thread showThread = new Thread(ThreadStateNRWRTLockSupport::run);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());
        //循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
        while (true){
            if(showThread.getState()==Thread.State.WAITING){
                log.info(showThread.getName()+ ":" + showThread.getState());
                break;
            }
        }
        LockSupport.unpark(showThread);

        try {
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run() {
        //等待
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        LockSupport.park();
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());

    }

}

运行结果为:

18:54:02.446 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:NEW
18:54:02.449 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:RUNNABLE
18:54:02.552 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:WAITING
18:54:02.552 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:RUNNABLE
18:54:02.552 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:TERMINATED

不难发现以上例子中,线程的状态转换都是一致的,都是

NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED

4.NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
能造成TIMED_WAITING状态的行为有多种:

方法 运用
wait(long timeout) 同步代码块/方法中调用锁对象的wait(long timeout)方法
join(long millis) 线程对象调用join(long millis)方法
parkNanos(long nanos) 直接调用LockSupport的静态方法parkNanos(long nanos)
parkUntil(long deadline) 直接调用LockSupport的静态方法parkUntil(long deadline)
await(long time, TimeUnit unit) 调用Condition实现类的对象的await(long time, TimeUnit unit)方法

这里展示2种:
1.wait(long timeout)

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRTWRT {

    //锁
    private static final Object lock=new Object();

    public static void main(String[] args) {

        //展示线程
        Thread showThread = new Thread(ThreadStateNRTWRT::run);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());
        while (true){
            if(showThread.getState()==Thread.State.TIMED_WAITING){
                log.info(showThread.getName()+ ":" + showThread.getState());
                break;
            }
        }

        try {
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run() {

        //等待
        synchronized (lock){
            try {
                Thread.sleep(100);
                lock.wait(1);
            } catch (InterruptedException e) {
                log.error(e.getMessage(),e);
                Thread.currentThread().interrupt();
            }
        }
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());

    }

}

运行结果为:

19:08:46.182 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:NEW
19:08:46.185 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:RUNNABLE
19:08:46.185 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:TIMED_WAITING
19:08:46.291 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:RUNNABLE
19:08:46.291 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:TERMINATED

2.await(long time, TimeUnit unit)

package com.zaomianbao.java8.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
 * @Author zaomianbao
 * @Date 2019/5/31
 **/
@Slf4j
public class ThreadStateNRTWRTCondition {
    //锁
    private static Lock lock=new ReentrantLock();
    private static Condition condition=lock.newCondition();

    public static void main(String[] args) {

        //展示线程
        Thread showThread = new Thread(ThreadStateNRTWRTCondition::run);
        log.info(showThread.getName()+ ":" + showThread.getState());
        showThread.start();
        log.info(showThread.getName()+ ":" + showThread.getState());

        //循环读取展示线程状态,直到读到展示线程状态为TIMED_WAITING。
        while (true){
            if(Thread.State.TIMED_WAITING==showThread.getState()){
                log.info(showThread.getName()+ ":" + showThread.getState());
                break;
            }
        }
        try {
            showThread.join();
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }

        //线程执行完毕打印状态。
        log.info(showThread.getName()+ ":" + showThread.getState());
    }

    private static void run() {
        //等待
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            Thread.currentThread().interrupt();
        }
        lock.lock();
        try{
            try {
                if (condition.await(1, TimeUnit.MILLISECONDS)){
                    log.info("及时返回释放");
                }else {
                    log.info("超时未返回释放");
                }
            } catch (InterruptedException e) {
                log.error(e.getMessage(),e);
                Thread.currentThread().interrupt();
            }
        }finally {
            lock.unlock();
        }
        log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
    }

}

运行结果为:

19:09:36.889 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:NEW
19:09:36.893 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:RUNNABLE
19:09:36.893 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:TIMED_WAITING
19:09:36.996 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - 超时未返回释放
19:09:36.996 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:RUNNABLE
19:09:36.996 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:TERMINATED

不难发现以上例子中,线程的状态转换都是一致的,都是

NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED

参考:

1.https://segmentfault.com/a/1190000016197831?utm_source=tag-newest
2.https://www.cnblogs.com/happy-coder/p/6587092.html
3.https://www.cnblogs.com/hejing-swust/p/8038263.html
4.https://blog.csdn.net/pange1991/article/details/53860651