我是新来的Groovy和这个简单的代码片段:
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
CountDownLatch called = new CountDownLatch(1)
Timer timer = new Timer()
timer.schedule(new TimerTask() {
void run() {
called.countDown()
}
}, 0)
assert called.await(2, TimeUnit.SECONDS)
在命令行上运行,它只是挂在那里,没有发生。我希望这个节目应该退出一次。那么,我才拿到了?
其实,这不是await
导致挂在你的情况。这只是Timer
的线程不是一个守护进程。该JVM不能终止,直到所有剩余的正在运行的线程是守护进程。作为Thread#setDaemon()
javadoc指出它:
... Java虚拟机退出时正在运行的线程都是守护线程。
所以你的情况
CountDownLatch called = new CountDownLatch(1)
Timer timer = new Timer(true) //true means the underlying thread is a daemon
timer.schedule(new TimerTask() {
void run() {
called.countDown()
}
}, 0)
assert called.await(2, TimeUnit.SECONDS)
println("It's not await that leads to hanging")
CountDownLatch called = new CountDownLatch(1)
Timer timer = new Timer() //now the underlying thread is NOT a daemon
timer.schedule(new TimerTask() {
void run() {
called.countDown()
}
}, 0)
assert called.await(2, TimeUnit.SECONDS)
println("It's not await that leads to hanging")
timer.cancel()//now we are done. All scheduled tasks will be cancelled. However, the running one will finish its job
附:如果你想调度更灵活的方式,你可以看看ScheduledThreadPoolExecutor。作为Timer
s的javadoc说:
......这实际上是定时器/ TimerTask的组合更灵活的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要TimerTask的子类(只实现Runnable)。配置的ScheduledThreadPoolExecutor使用一个线程使其等同于定时器。