Groovy中调用CountDownLatch.await()导致挂

问题描述 投票:1回答:1

我是新来的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)

在命令行上运行,它只是挂在那里,没有发生。我希望这个节目应该退出一次。那么,我才拿到了?

groovy timer async-await
1个回答
2
投票

其实,这不是await导致挂在你的情况。这只是Timer的线程不是一个守护进程。该JVM不能终止,直到所有剩余的正在运行的线程是守护进程。作为Thread#setDaemon() javadoc指出它:

... Java虚拟机退出时正在运行的线程都是守护线程。

所以你的情况

  1. 你可以只指定计时器的线程是守护
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")
  1. 或者,如果由于某种原因,你不希望你的计时器的线程是一个守护进程。例如。您希望定时器来处理所有的计划任务的JVM终止之前。在这种情况下,你可以取消计时器在某个适当的时候
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。作为Timers的javadoc说:

......这实际上是定时器/ TimerTask的组合更灵活的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要TimerTask的子类(只实现Runnable)。配置的ScheduledThreadPoolExecutor使用一个线程使其等同于定时器。

© www.soinside.com 2019 - 2024. All rights reserved.