5

I am using a CountDownLatch to handle two Java threads. My class structure is as follows:

MainClass.java
ThreadOne.java
ThreadTwo.java

MainClass:

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);

Main class waits until other two threads complete their work. As soon as they complete their work it does not wait until its timeout value (20 secs). My problem is if any of the threads get destroyed or corrupted then the CountDownLatch waits for its timeout value. Is there any way to ignore that interrupted thread and move forward without waiting 20 seconds?

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
NPrasad
  • 108
  • 1
  • 6
  • What do you mean with your Threads getting destroyed or corrupted? Throwing an Exception? – Alexander May 18 '16 at 11:52
  • 5
    move the `latch.countDown()` call in your thread code into a `finally` block so it gets executed no matter what happens – zapl May 18 '16 at 11:57

2 Answers2

7

zapl is absolutely right! The main thread is waiting for the timeout to get over. If you took a thread dump during the time that the main thread is waiting on the latch, you will see something like:

"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)

From the Javadoc of await:

If the current count is greater than zero then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happen:

  1. The count reaches zero due to invocations of the countDown method; or
  2. Some other thread interrupts the current thread; or
  3. The specified waiting time elapses.

In your case, the await call returns only because of 3).

In the CountDownLatch Javadoc, the call to the countDown() method should have been done in the finally block:

public void run() {
    try {
        startSignal.await();
        doWork(); // may throw exception
    } catch (InterruptedException ex) {
        // handle interruption ...
    } finally {
        doneSignal.countDown(); // cause await to return asap
    }
}
Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
0

You need some sort of notification when a thread gets destroyed. One way to do so is to catch the InterruptedException manually within the thread, then count down the error.

Another way is to use Runnable tasks instead of Threads and use guavas ListenableFuture to get error notifications. This SO Q&A explains it well.

Community
  • 1
  • 1
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49