开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
学习MOOC视频记录的笔记
线程的一生——6个状态(生命周期)
1.有哪6种状态?
- New
- Runnable
- Blocked
- Waiting
- Timed Waiting
- Terminated
2.每个状态是什么含义?
| 状态 | 含义 |
|---|---|
New | 已创建但还没启动的新线程,也就是创建了一个线程但是还没有执行 start 方法时候的状态,即做了一些准备工作,但是还没有执行 run 方法里面的代码 |
Runnable | 可运行的,只要调用了 start 就进入这个状态,对应着操作系统中的两种状态,分别是 Ready 和 Running 即可以是可运行的,又可以是实际运行中的。如果一个正在运行的线程的 CPU 资源被抢走了,对应的状态还是 Runnable 的 |
Blocked | 当一个线程进入被 synchronized 修饰的代码块的时候,如果该锁已经被其他的线程拿走了,这个线程就进入了 Blocked 状态;注意一定是 synchronized 修饰的部分 |
Waiting | 等待,没有设置 timeout 参数的 Object 中的 wait 方法 |
Timed Waiting | 计时等待,超时的时候会被自动唤醒,也可以由唤醒信号提前唤醒 |
Terminated | 终止状态,执行完成。情况1:①程序正常执行退出;②出现了一个异常 |
3.状态间的转化图示
状态转化的特殊情况
- 从
Object.wait状态刚被唤醒时,通常不能立刻抢到monitor锁,那就会从Waiting先进入Blocked状态 ,抢到锁后再转换到Runnable状态(官方文档)- 如果发生异常,可以直接跳到终止
Terminated状态,不必再遵循路径,比如可以从Waiting直接到Terminated
/**
* 展示线程的NEW、RUNNABLE、Terminated状态。
* 即使是正在运行,也是Runnable状态而不是Running
*/
public class NewRunnableTerminated implements Runnable {
public static void main(String[] args) {
Thread thread = new Thread(new NewRunnableTerminated());
// 打印出NEW的状态
System.out.println(thread.getState());
thread.start();
System.out.println(thread.getState());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印出RUNNABLE的状态,即使是正在运行,也是RUNNABLE,而不是RUNNING
System.out.println(thread.getState());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印出TERMINATED的状态
System.out.println(thread.getState());
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
}
部分运行结果如下:
/**
* 展示Blocked,Waiting,TimedWaiting
*/
public class BlockedWaitingTimedWaiting implements Runnable {
public static void main(String[] args) {
BlockedWaitingTimedWaiting runnable = new BlockedWaitingTimedWaiting();
Thread thread1 = new Thread(runnable);
thread1.start();
Thread thread2 = new Thread(runnable);
thread2.start();
// 避免主线程运行过快输出两个RUNNABLE状态的情况
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印出TIMED_WAITING状态,因为正在执行Thread.sleep(1000);
System.out.println(thread1.getState());
// 打印出BLOCKED状态,因为thread2想拿到sync()的锁却拿不到
System.out.println(thread2.getState());
try {
Thread.sleep(1300);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印出WAITING状态
System.out.println(thread1.getState());
}
@Override
public void run() {
syn();
}
/**
* 第一个线程进来获得锁,并sleep(1000),进入TimedWaiting状态
* 此时第二个线程无法获取锁,进入Blocked状态
*/
private synchronized void syn() {
try {
Thread.sleep(1000);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
程序运行结果:
TIMED_WAITING
BLOCKED
WAITING
- 有一些状态是没有回头路的,左侧三个是从上往下的。
- 状态之间是不能跳跃的。
4.阻塞状态是什么?
一般习惯而言,把 Blocked(被阻塞)、Waiting(等待)、Timed_waiting(计时等待)都称为阻塞状态,都是使线程陷入一种阻塞的状态。不仅仅是 Blocked。
被阻塞的情况下什么时候被唤醒能继续运行是不受到我的控制的,比如等待 synchronized 锁,有可能永远无法获得锁,陷入死锁的情况。
5.常见面试问题
线程有哪几种状态?生命周期是什么?
见上图