OS 线程状态
- NEW(新建):创建状态,当调用new Thread(runnable)后创建一个线程。
- RUNNABLE(就绪):就绪状态,当线程调用了start启动线程后,线程进入就绪状态,此时它随时会被CPU调度启用。
- RUNNING(运行):运行状态,线程被CPU调度执行的过程。
- BLOCKED(阻塞):阻塞状态,当线程调用sleep或者wait方法或者线程等待获取被其他线程持有的锁的时候,被称为阻塞状态,当线程获得了锁或者被唤醒等将再次进入运行状态。
- TERMINATED(终止):终止状态,当线程任务执行完成了或者被强行终止了,就进入终止状态,并且线程进入了终止状态后无法再恢复到其它状态。
Java#Thread线程状态
今天看Thread源码,发现Thread内部有public枚举State,描述了Thread在应用层面的几种线程状态,根据源码注释知道了它和操作系统线程状态略有差异。
public enum State {
NEW,// 创建状态
RUNNABLE,// 运行状态
BLOCKED,// 阻塞状态
WAITING,// 等待状态
TIMED_WAITING,// 有时限的等待状态
TERMINATED;// 终止状态
}
可以看到Java的Api Thread的状态比操作系统的线程状态多一个状态,并且没有就绪状态;java线程操作系统的RUNNABLE和RUNNING统一归类到RUNNABLE状态,将阻塞等待分为了三个,分别是BLOCKED、WAITING、TIME_WAITING状态。
Java和OS线程状态对应关系
状态演示
NEW
线程创建状态,当Java里面调用了new Thread(),在构造方法里面会调用init方法,进行各种初始化操作,包括分配ThreadID,获取ClassLoader等操作,在这里就创建了 一个线程。
Thread thread = new Thread(() -> {
System.out.println("");
});
System.out.println("线程创建:" + thread.getState());// 线程创建:NEW
RUNNABLE
因为在Java中Thread是应用层面的API,它无法直接感知到内核对线程的操作,因此将操作系统线程的RUNNABLE(就绪)和RUNNING(运行)统一归到运行状态。对Java来说,只要线程没有终止或者阻塞都属于在正常运行状态。
这一块用代码不好演示,因为一旦执行到了Thread的钩子方法run,那么这个Thread代表的线程肯定是已经是运行状态了,无法监控到就绪状态。
BLOCKED
BLOCKED
1、尝试获取被其它线程持有的锁(Java BLOCKED)
// 创建一个线程,在一秒钟后尝试获取锁
Thread thread = new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("尝试获取锁....");
synchronized (lock){
System.out.println("Thread run.....");
}
});
thread.start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 主线程持有锁,不释放,并监控控制台,如果控制台输入state,则打印创建的线程状态
synchronized (lock){
while(true){
String readLine = br.readLine();
if("state".equals(readLine)){
System.out.println("线程创建:" + thread.getState());
}
}
}
结果:
尝试获取锁....
state
线程状态:BLOCKED
可以看到,当线程在等待获取锁的时候,Thread的状态是BLOCKED。
WAITING
Thread的WAITING是当线程被暂时挂起,等待唤醒的情况出现的状态
Thread thread = new Thread(() -> {
synchronized (lock){
// 线程等待
lock.wait();
System.out.println("Thread run.....");
}
});
thread.start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(true){
String readLine = br.readLine();
if("state".equals(readLine)){
System.out.println("线程创建:" + thread.getState());
}
}
结果:
state
线程状态:WAITING
TIMED_WAITING
Thread thread = new Thread(() -> {
// 线程超时等待
TimeUnit.SECONDS.sleep(10000);
System.out.println("Thread run.....");
});
thread.start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String readLine = br.readLine();
if ("state".equals(readLine)) {
System.out.println("线程状态:" + thread.getState());
}
}
结果:
state
线程状态:TIMED_WAITING
TERMINATED
Thread thread = new Thread(() -> {
System.out.println("Thread run.....");
});
thread.start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String readLine = br.readLine();
if ("state".equals(readLine)) {
System.out.println("线程状态:" + thread.getState());
}
}
结果:
Thread run.....
state
线程状态:TERMINATED
因为线程执行得很快,因此执行完后查看线程状态已经终止了。
总结
Java中的Thread是API层面的线程,它对线程与内核交互无法感知,因此将操作系统线程的就绪
和运行
统一归纳到了运行
状态,对于Java来说只要线程没有终止和阻塞都是运行
状态。
在Java中要使得线程阻塞,都必须要过JVM,比如synchronized获取锁操作,wait(),sleep(timeout)等,都是通过JVM层面实现的,对于JVM可以监控到的每次阻塞的原因和操作类型,因此Thread的阻塞分为了BLOCKED
、WAITING
、TIMED_WAITING
。