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

时间:2019-02-03 01:10:31

标签: groovy timer async-await

我是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)

在命令行上运行时,它只是挂在那里,什么也没有发生。我希望该程序应立即退出。那我哪里做错了?

1 个答案:

答案 0 :(得分: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

P.S。如果您想要更灵活的计划方式,可以看看ScheduledThreadPoolExecutor。正如Timer的javadoc所说:

  

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