图形说明:
Thread.State源码注释:
java
public enum State {
/**
* 新生状态:线程对象创建,但是还未start()
*/
NEW,
/**
* 线程处于可运行状态,但是这个可运行状态并不代表线程一定在虚拟机中执行。
* 需要等待从操作系统获取到资源(比如处理器时间片),才能真正的去运行
*/
RUNNABLE,
/**
* 当前线程处于阻塞状态,正在等待另一个线程的monitor lock释放,才进入synchronized代码块或方法
*/
BLOCKED,
/**
* 调用Object#wait() 、 Thread.join方法后当前线程处于等待状态,
* 等待其他的线程执行特定的动作,才能从等待状态退出。
* 比如:Object.wait()的线程需要等待其他线程调用Object.notify()、Object.notifyAll()才能退出
* 比如:调用了Thread.join()的线程需要等待指定的线程执行完成才能退出等待状态。
*/
WAITING,
/**
* 进入特定时间内的等待状态,等待一段指定的时间sleep(timed)、wait(timed)或者等待Thread.join(timed)的时间.
* 到达指定时间点自动退出恢复到RUNNABLE状态
*/
TIMED_WAITING,
/**
* 线程结束状态
*/
TERMINATED;
}
代码示例:
NEW状态:
java
public class ThreadState {
public static void main(String[] args) throws Exception {
Thread thread = new Thread();
System.out.println(thread.getState());
}
}
结果:
RUNNABLE状态:
java
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
while (true){
Thread.yield();
}
});
thread.start();
Thread.sleep(2000);
System.out.println(thread.getState());
}
}
结果:
WAITING状态:
java
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
LockSupport.park();
while (true){
Thread.yield();
}
});
thread.start();
Thread.sleep(50);
System.out.println(thread.getState());
LockSupport.unpark(thread);
Thread.sleep(50);
System.out.println(thread.getState());
}
结果:
join方法代码:
可见Thread#join()是在线程实例存活的时候总是调用Object#wait()方法,也就是必须在线程执行完毕isAlive()为false(意味着线程生命周期已经终结)的时候才会解除阻塞。
TIMED WAITING状态:
java
public static void main(String[] args) throws Exception {
Thread thread = new Thread(()-> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//ignore
}
});
thread.start();
thread.notify();
Thread.sleep(50);
System.out.println(thread.getState());
Thread.sleep(1000);
System.out.println(thread.getState());
}
结果:
BLOCKED状态:
BLOCKED状态也就是阻塞状态,该状态下的线程不会被分配CPU执行时间。线程的状态为BLOCKED的时候有两种可能的情况:
A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method
1.线程正在等待一个监视器锁,只有获取监视器锁之后才能进入synchronized代码块或者synchronized方法,
在此等待获取锁的过程线程都处于阻塞状态。
reenter a synchronized block/method after calling Object#wait()
2.线程X步入synchronized代码块或者synchronized方法后(此时已经释放监视器锁)调用Object#wait()方法之后进行阻塞,
当接收其他线程T调用该锁对象Object#notify()/notifyAll(),但是线程T尚未退出它所在的synchronized代码块或者synchronized方法,
那么线程X依然处于阻塞状态(注意API注释中的reenter,理解它场景2就豁然开朗)。
java
private static final Object MONITOR = new Object();
private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) throws Exception {
System.out.printf("[%s]-begin...%n", F.format(LocalDateTime.now()));
Thread thread1 = new Thread(() -> {
synchronized (MONITOR) {
System.out.printf("[%s]-thread1 got monitor lock...%n", F.format(LocalDateTime.now()));
try {
Thread.sleep(1000);
MONITOR.wait();
} catch (InterruptedException e) {
//ignore
}
System.out.printf("[%s]-thread1 exit waiting...%n", F.format(LocalDateTime.now()));
}
});
Thread thread2 = new Thread(() -> {
synchronized (MONITOR) {
System.out.printf("[%s]-thread2 got monitor lock...%n", F.format(LocalDateTime.now()));
try {
MONITOR.notify();
//这个时候thread2已经释放了MONITOR锁,thread1已经被唤醒,但是因为thread2还在占用MONITOR,所以thread1是blocked状态
//对应 reenter a synchronized block/method after calling Object#wait()
Thread.sleep(2000);
} catch (InterruptedException e) {
//ignore
}
System.out.printf("[%s]-thread2 releases monitor lock...%n", F.format(LocalDateTime.now()));
}
});
thread1.start();
thread2.start();
// 这里故意让主线程sleep 1500毫秒从而让thread2调用了Object#notify()并且尚未退出同步代码块,确保thread1调用了Object#wait()
Thread.sleep(1500);
System.out.println(thread1.getState());
System.out.printf("[%s]-end...%n", F.format(LocalDateTime.now()));
}
结果:
源码的注释说的就是上述测试的情况,虽然调用了notify方法,但是被唤醒的线程并不会进入RUNNABLE状态,需要等thread2释放锁以后重新参与锁竞争;
TERMINATED状态:
java
public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> {
});
thread.start();
Thread.sleep(50);
System.out.println(thread.getState());
}
结果: