介于“直接balk并返回”和“等待到守护条件成立为止”这两种极端的处理方法之间,还有一种处理方法,那就是“在守护条件成立之前等待一段时间”。在守护条件成立之前等待一段时间,如果到时条件还未成立,则直接balk。将这种处理称为guarded timed或timeout。
wait何时终止
在调用Java的wait方法时,可以传入参数,以指定超过时间。
线程进入obj的等待队列,停止运行,并释放持有的obj锁。当下列情况发生时,线程便会退出等待队列。
notify方法执行时
即obj的notify方法被执行后,线程被唤醒了的情况。
但当等待队列中有多个等待线程时,只能有一个线程被唤醒。到底唤醒哪一个线程,Java规范中并没有明确规定。
notifyAll方法执行时
即obj的notifyAll方法被执行了的情况。
notifyAll会唤醒实例的等待队列中的所有线程。不管是notify,还是notifyAll,线程被唤醒后,都必须重新获取obj的锁。
interrupt方法执行时
即线程的interrupt方法被执行了的情况。
当被interrupt时,等待队列中的线程(与被notify、notifyAll时一样)会重新获取obj的锁,然后抛出InterruptedException异常。
notify和notifyAll这两个方法是用于调用实例的,而interrupt方法是用于调用线程的。
超时发生时
即wait方法的参数中指定的超时时间到期的情况。
与被notify、notifyAll时一样,这时也要重新获取obj的锁。
guarded timed的实现
使用wait方法来实现guarded timed。超时异常使用java.util.concurrent.TimeoutException。
Host.java
1 | import java.util.concurrent.TimeoutException; |
Main.java
1 | import java.util.concurrent.TimeoutException; |
运行结果
1 | execute BEGIN |
java.util.concurrent中的超时
java.util.concurrent包中提供了如下两个用于超时处理的方法。
通过异常通知超时
当发生超时抛出异常时,返回值并不适合用于表示超时,需要使用java.util.concurrent.TimeoutException异常。
- java.util.concurrent.Future接口的get方法
- java.util.concurrent.Exchanger类的exchange方法
- java.util.concurrent.Cyclicarrier类的await方法
- java.util.concurrent.CountDownLatch类的await方法
通过返回值通知超时
当执行多次try时,则不使用异常,而是使用返回值来表示超时。
- java.util.concurrent.BlockingQueue接口
- java.util.concurrent.Semaphore类
- java.util.concurrent.locks.lock接口