java Thread类中定义了线程的六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
- NEW、RUNNABLE、TERMINATED
- 新建还没有Start的线程状态为NEW
- 线程本身没有被其他线程阻塞,等待cpu调度或者用户io的线程状态为RUNNABLE
- 运行结束状态为TERMINATED
-WAITING 和 BLOCKED
BLOCKED 与 WAITING 的区别在于BLOCKED是等待锁时的状态
示例:
class ThreadA3 extends Thread {
private Object lock;
public ThreadA3(Object lock) {
this.lock = lock;
}
@Override
public void run() {
System.out.println("ThreadA started.");
synchronized (lock) {
System.out.println("ThreadA get the lock.");
try {
sleep(3000);
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ThreadA release the lock.");
System.out.println("ThreadA end.");
}
}
class ThreadB3 extends Thread {
private Object lock;
public ThreadB3(Object lock) {
this.lock = lock;
}
@Override
public void run() {
System.out.println("ThreadB started.");
synchronized (lock) {
System.out.println("ThreadB get the lock.");
lock.notify();
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ThreadB release the lock.");
System.out.println("ThreadB end.");
}
}
运行结果:
ThreadA started.
ThreadA get the lock.
ThreadB started.
Thread A:TIMED_WAITING,Thread B:BLOCKED
Thread A:TIMED_WAITING,Thread B:BLOCKED
Thread A:TIMED_WAITING,Thread B:BLOCKED
Thread A:TIMED_WAITING,Thread B:BLOCKED
ThreadB get the lock.
Thread A:BLOCKED,Thread B:TIMED_WAITING
Thread A:BLOCKED,Thread B:TIMED_WAITING
Thread A:BLOCKED,Thread B:TIMED_WAITING
Thread A:BLOCKED,Thread B:TIMED_WAITING
Thread A:BLOCKED,Thread B:TIMED_WAITING
Thread A:BLOCKED,Thread B:TIMED_WAITING
ThreadB release the lock.
ThreadB end.
ThreadA release the lock.
ThreadA end.
1)线程A先启动并获得锁,调用sleep 进入TIMED_WAITING状态
2)线程B竞争锁失败,进入 BLOCKED 状态
3)线程A调用wait方法释放锁并等待唤醒
4)线程B获得锁并唤醒线程A,自己进入TIMED_WAITING状态
5)线程A被唤醒后尝试重新获取锁但失败,进入BLOCKED状态
6)线程B结束并释放锁
7)线程A获得锁并结束线程
总结
- 新建未start的线程状态为NEW
- 调用wait、join并且没设置超时的线程状态为WAITING
- 调用wait、join、sleep并且设置超时的线程状态为TIMED_WAITING
- 等待锁的线程状态为BLOCKED
- 其他运行中的线程状态为RUNNABLE
- 运行结束的线程状态为TERMINATED
附线程易混淆状态区别:
一、 sleep()和wait()方法的区别
sleep()方法
sleep()方法是Thread类的方法,通过其定义可知是个native方法,在指定的时间内阻塞线程的执行。而且从其注释中可知,并不会失去对任何监视器(monitors)的所有权,也就是说不会释放锁,仅仅会让出cpu的执行权。如下图所示
wait()方法
wait()方式是基类Object的方法,其实也是个native方法
不管是wait()还是wait(long timeout, int nanos),其调用的都是wait(long timeout)
The current thread must own this object's monitor
根据注释中的一句话,可以看出此方法调用的前提是当前线程已经获取了对象监视器monitor的所有权。
调用它的前提是当前线程占有锁(即代码要在synchronized中),该方法会调用后不仅会让出cpu的执行权,还会释放锁(即monitor的所有权),并且进入wait set中,知道其他线程调用notify()或者notifyall()方法,或者指定的timeout到了,才会从wait set中出来,并重新竞争锁。
区别
最主要的区别就是释放锁(monitor的所有权)与否,但是两个方法都会抛出InterruptedException。
二、线程阻塞BLOCKED和等待WAITING的区别
阻塞BLOCKED
阻塞表示线程在等待对象的monitor锁,试图通过synchronized去获取某个锁,但是此时其他线程已经独占了monitor锁,那么当前线程就会进入等待状态。
等待WAITING
当前线程等待其他线程执行某些操作,典型场景就是生产者消费者模式,在任务条件不满足时,等待其他线程的操作从而使得条件满足。可以通过wait()方法或者Thread.join()方法都会使线程进入等待状态。
实际上可以不用区分两者, 因为两者都会暂停线程的执行. 两者的区别是: 进入waiting状态是线程主动的, 而进入blocked状态是被动的. 更进一步的说, 进入blocked状态是在同步(synchronized)代码之外, 而进入waiting状态是在同步代码之内.