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

Groovy调用CountDownLatch.wait()导致挂起,groovy,timer,async-await,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.countDow

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

在命令行上运行时,它只是挂在那里,什么也没发生。我希望这个项目应该立即退出。那么我哪里弄错了呢?

事实上,并不是
wait
导致你被绞死。只是
计时器
的线程不是守护进程。在所有剩余的运行线程都是守护进程之前,JVM无法终止。正如
Thread#setDaemon()
所述:

…当运行的线程都是守护进程线程时,Java虚拟机将退出

那么你的情况呢

  • 您可以只指定计时器的线程是守护进程
  • 或者如果出于某种原因,您不希望计时器的线程成为守护进程。例如,您希望计时器在JVM终止之前处理所有计划的任务。在这种情况下,您可以在适当的时候取消计时器
  • 另外,如果你想要更灵活的安排方式,你可以看看。正如
    计时器
    s javadoc所说:

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

    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