【问题标题】:Java CountDownLatch waits for the timeout value when the thread.run() counting down the latch gets an exceptionJava CountDownLatch 在 thread.run() 倒计时获得异常时等待超时值
【发布时间】:2016-05-18 11:49:20
【问题描述】:

我使用CountDownLatch 来处理两个Java 线程。我的班级结构如下:

MainClass.java
ThreadOne.java
ThreadTwo.java

主类:

CountDownLatch latch = new CountDownLatch(2);           
Thread thread = new Thread(new ThreadOne(latch));
thread.start();

Thread thread1 = new Thread(new ThreadTwo(latch));
thread1.start();        

latch.await(20, TimeUnit.SECONDS);

主类等待其他两个线程完成它们的工作。一旦他们完成他们的工作,它就不会等到它的超时值(20 秒)。我的问题是,如果任何线程被破坏或损坏,那么CountDownLatch 将等待其超时值。有什么方法可以忽略该中断的线程并在不等待 20 秒的情况下继续前进?

【问题讨论】:

  • 你的线程被破坏或损坏是什么意思?抛出异常?
  • 将线程代码中的 latch.countDown() 调用移动到 finally 块中,以便无论发生什么都会执行

标签: java multithreading countdownlatch


【解决方案1】:

zapl 是绝对正确的!主线程正在等待超时结束。如果您在主线程等待闩锁期间进行线程转储,您将看到如下内容:

"main" #1 prio=5 os_prio=31 tid=0x00007fa4be002000 nid=0x1303 waiting on condition [0x000000010b74c000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076abcb598> (a java.util.concurrent.CountDownLatch$Sync)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1037)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1328)
    at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:277)

来自await的Javadoc:

如果当前计数大于零,则当前线程 出于线程调度目的而被禁用并处于休眠状态,直到 发生以下三件事之一:

  1. 由于调用 countDown 方法,计数达到零;或
  2. 其他线程中断当前线程;或
  3. 指定的等待时间已过。

在您的情况下,await 调用仅因为 3) 而返回。

CountDownLatch Javadoc 中,对countDown() 方法的调用应该在finally 块中完成:

public void run() {
    try {
        startSignal.await();
        doWork(); // may throw exception
    } catch (InterruptedException ex) {
        // handle interruption ...
    } finally {
        doneSignal.countDown(); // cause await to return asap
    }
}

【讨论】:

    【解决方案2】:

    当线程被销毁时,您需要某种通知。一种方法是在线程中手动捕获InterruptedException,然后倒计时错误。

    另一种方法是使用Runnable 任务而不是Threads 并使用番石榴ListenableFuture 来获取错误通知。 ThisSO Q&A 解释的很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 1970-01-01
      相关资源
      最近更新 更多