目录
- 一、简介
- 二、线程状态
- 1、新建状态(New)
- 2、运行状态(Runnable)
- 3、阻塞状态(Blocked/Waiting/TimeWaiting)
- (1)被阻塞状态(Blocked)
- (2)等待状态(Waiting)
- (3)超时等待状态(TimeWaiting)
- 4、终止状态(Terminated)
- 三、总结
- 四、示例
一、简介
线程的六种状态:
New- 新建状态;Runnable- 运行状态;Blocked- 被阻塞状态;Waiting- 等待状态;TimeWaiting- 超时等待状态;Terminated- 终止状态;
线程状态之间的转换图:
二、线程状态
1、新建状态(New)
New:线程被创建,但尚未启动的状态。
当我们用 new Thread(); 新建一个线程时,如果线程没有开始执行 start() 方法,所以没有开始执行 run() 方法里面的代码,那么线程此时的状态就是 New。而一旦线程调用了 start() 方法,它的状态就会从 New 变成 Runnable。
2、运行状态(Runnable)
Java 中的 Runnable 状态对应操作系统线程状态中的两种状态:
Runnable- 运行状态;Ready- 就绪状态,正在等待被分配CPU资源;
如果一个正在运行的线程是 Runnable 状态,当它运行到任务的一半时,执行该线程的 CPU 被调度去做其他事情,导致该线程暂时不运行,它的状态依然是 Runnable,因为它有可能随时被调度回来继续执行任务。
3、阻塞状态(Blocked/Waiting/TimeWaiting)
在 Java 中阻塞状态包括三种状态:
-
Blocked- 被阻塞状态; -
Waiting- 等待状态; -
TimeWaiting- 超时等待状态;
(1)被阻塞状态(Blocked)
线程 Blocked 状态的转换:
-
Runnable 状态进入 Blocked 状态:进入synchronized保护的代码(包括:synchronized代码块和synchronized方法)时没有抢到monitor锁。 -
Blocked 状态回到 Runnable 状态:处于Blocked的线程抢到monitor锁。
(2)等待状态(Waiting)
线程进入 Waiting 状态有以下三种可能:
-
run()方法中调用Object.wait(); -
run()方法中调用Thread.join(); -
run()方法中调用LockSupport.park();
前面强调了 Blocked 是针对 synchronized monitor 锁,可是在 Java 中还有很多其他锁,比如 ReentrantLock,如果线程在获取这种锁时,没有抢到该锁,就会进入 Waiting 状态,因为本质上它执行了 LockSupport.park() 方法,所以会进入 Waiting 状态,同样,Object.wait() 和 Thread.join() 也会让线程进入 Waiting 状态。
Blocked 与 Waiting 的区别:
-
Blocked在等待其他线程释放monitor锁; -
Waiting在等待某个条件,比如join的线程执行完毕或者是notify()/notifyAll();
Waiting 状态流转到其他状态比较特殊,因为 Waiting 是不限时的,也就是说无论过了多长时间它都不会主动恢复。
线程 Waiting 状态的转换:
-
当执行了
LockSupport.unpark(),或者join()的线程运行结束,或者被中断时,线程才会从Waiting状态进入Runnable状态; -
其他线程如果调用了
notify()或notifyAll()来唤醒它,线程会直接进入Blocked状态(因为唤醒Waiting线程的线程如果调用了notify()或notifyAll(),要求首先要持有该monitor锁,所以处于Waiting状态的线程被唤醒时拿不到该锁,就会进入Blocked状态,直到执行了notify()/notifyAll()的唤醒它的线程执行完毕并释放了monitor锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从Blocked状态回到Runnable状态);
(3)超时等待状态(TimeWaiting)
TimeWaiting 与 Waiting 状态非常相似,区别仅仅在于有没有超时限制,TimeWaiting 会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。
线程进入 TimeWaiting 状态有以下几种可能:
-
run()方法中调用Thread.sleep(sleeptime); -
run()方法中调用Object.wait(timeout); -
run()方法中调用Thread.join(timeout); -
run()方法中调用LockSupport.parkNanos(timeout); -
run()方法中调用LockSupport.parkUntil(timeout);
线程 TimeWaiting 状态的转换:
-
如果
TimeWaiting超时时间未超时,当其他线程调用了notify()或notifyAll(),TimeWaiting状态的线程会先进入Blocked状态,然后抢夺monitor锁成功后,再会进入到Runnable状态,此种情况下TimeWaiting与Waiting状态一样的; -
如果
TimeWaiting超时时间超时,且能直接获取到锁 / join的线程运行结束 / 被中断 / 调用了LockSupport.unpark(),会直接恢复到Runnable状态;
4、终止状态(Terminated)
进入终止状态的两种可能:
-
线程正常退出:run()方法执行完毕; -
线程意外终止:出现一个没有捕获的异常,终止了run()方法;
三、总结
线程状态总结:
-
new Thread(),但没有调用start()方法,线程处于New状态; -
new Thread(),且调用了start()方法,线程处于Runnable状态; -
new Thread(),且调用了start()方法,run()方法中调用了thread.join()或object.wait()方法,线程处于Waiting状态; -
new Thread(),且调用了start()方法,run()方法中调用了Thread.sleep(sleeptime)方法,线程处于TimeWaiting状态; -
new Thread(),且调用了start()方法,run()方法中获取monitor锁,且没有获取到,线程处于Blocked状态; -
new Thread(),且调用了start()方法,run()方法正常执行完毕或抛出未捕获的异常而结束,线程处于Terminated状态;
线程转换注意事项:
-
线程状态是需要按照箭头方向流转:比如线程从New状态是不可以直接进入Blocked状态的,它需要先经历Runnable状态; -
线程生命周期不可逆:一旦进入Runnable状态就不能回到New状态,一旦终止就不可能再有任何状态变化,所以一个线程只能有一次New和Terminated状态,只有处于中间状态才可以相互转换;
四、示例
六种线程状态示例:
package com.cw.tsb.test;
/**
* @author Davis
* @Date 2022-12-29 11:27 上午
*/
public class ThreadStateTest {
public static void main(String[] args) {
threadState();
}
private static void threadState(){
Thread t1 = new Thread("t1") {
@Override
public void run() {
System.out.println("running...");
}
};
Thread t2 = new Thread("t2") {
@Override
public void run() {
while(true) { // runnable
}
}
};
t2.start();
Thread t3 = new Thread("t3") {
@Override
public void run() {
System.out.println("running...");
}
};
t3.start();
Thread t4 = new Thread("t4") {
@Override
public void run() {
synchronized (ThreadStateTest.class) {
try {
Thread.sleep(1000000); // timed_waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t4.start();
Thread t5 = new Thread("t5") {
@Override
public void run() {
try {
t2.join(); // waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t5.start();
Thread t6 = new Thread("t6") {
@Override
public void run() {
synchronized (ThreadStateTest.class) { // blocked
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t6.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 state : " + t1.getState());
System.out.println("t2 state : " + t2.getState());
System.out.println("t3 state : " + t3.getState());
System.out.println("t4 state : " + t4.getState());
System.out.println("t5 state : " + t5.getState());
System.out.println("t6 state : " + t6.getState());
}
}
输出结果:
running...
t1 state : NEW
t2 state : RUNNABLE
t3 state : TERMINATED
t4 state : TIMED_WAITING
t5 state : WAITING
t6 state : BLOCKED












![写作历时一个月,长达8000字的年终总结——[2022年终总结]不要怕,请勇敢的向前走](https://img-blog.csdnimg.cn/img_convert/521792c93ed164bdb60b45bef8593c80.png)






