系列文章:
BLOCKED, WAITING状态描述
当一个线程调用Object.wait 或 Thread.join方法时,线程会进入 WAITING状态。
如果是调用Object.wait,在进入WAITING状态之前,线程会先释放它持有的对象锁,然后保持WAITING状态直到其他线程调用了同一个Object的notify或notifyAll方法。一旦在同一个对象上调用了notify或notifyAll,WAITING状态的线程中的一个或所有将被唤醒。如果对象锁被别的线程持有,则被唤醒的线程不会立即获得对象锁,而是进入BLOCKED状态。当前持有锁的线程一旦释放锁,这些被唤醒线程会比在那些还未进入同步代码块或方法的线程优先获得对象锁。
如果是调用Thread.join,在进入WAITING状态之前,线程不会释放锁,调join方法时也并不需要你一定要持有对象锁才能调。
Object.wait 和 Object.notify/notifyAll 是必须要持有对象锁才可以调用的。
可以看出WAITING状态和锁没有必然联系的,进入WAITING状态和退出WAITING状态都跟对象锁没有关系,虽然Object.wait会导致线程释放对象锁,但那只是Object.wait提供的一个特性,进入WAITING状态并不一定会跟释放锁联系在一起,Thread.join就跟锁没有关系。
BLOCKED和锁有必然的联系,如果线程进入BLOCKED状态,那么它一定是在等待获得锁,退出BLOCKED状态,一定是已经获得了锁。反过来看,如果一个线程获得了锁,会导致其他想要获得锁的线程进入BLOCKED状态,线程释放锁,会导致其他线程争抢锁,抢到锁就退出BLOCKED状态。但是线程获得锁,释放锁对其他处于WAITING状态的线程是没有任何影响的。
另外TIMED_WAITING 除了有个定时唤醒的时间外,本质上和WAITING是一样的。
简而言之,WAITING/TIMED_WAITING 只是线程本身暂停运行的一种状态,可以被外界唤醒或是达到某种条件被唤醒或这被打断(Interrupted)。而BLOCKED是线程本身想要运行,但是被锁给挡住了去路,并随时等待获取锁继续前进的一种状态。
WAITING/TIMED_WAITING 状态是可以被打断的,通过Thread.interrupt方法,也就是为什么Object.wait, Thread.join, Thread.sleep都会声明一个非运行是异常抛出InterruptedException。而BLOCKED的状态是不可以被打断的。
区别总结
进入机制
WAITING/TIMED_WAITING
通过调用:
- Object.wait
- Thread.join
- Thread.sleep
- LockSupport.park
BLOCKED
等待获得锁已进入同步块/方法,可能是从Object.wait然后唤醒进行等待获得锁。
退出机制
WAITING/TIMED_WAITING
- 通过调用Object.notify/notifyAll
- join的线程终止
- 定时时间到期
BLOCKED
获得锁。
可否能被打断
WAITING/TIMED_WAITING
可被打断,须要捕获InterruptedException异常
BLOCKED
不可被打断