How to explicitly release CountDownLatch

2.5k views Asked by At

Is there any way to explicitly release CountDownLatch - means without do countDown().

E.g.: Let say I am waiting for 100 threads to do countDown(), but if something fails, I would like to release this latch without anymore waiting. I was thinking to getCount() on latch & then in for cycle do countDown(), but its not optimal way.

Any suggestions / ideas ?

5

There are 5 answers

2
TheLostMind On

The CountDownLatch has an overloaded await() method which takes time and time unit as inputs and releases the lock once the given time elapses

0
Benjamin M On

You could use a Semaphore, which is close to a CountDownLatch and it's impl has methods for manipulating it: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html

5
mavarazy On

Why not just use await with timeout?

boolean await(long timeout, TimeUnit unit);

If the specified waiting time elapses then the value false is returned, otherwise true is returned on await completion.

Abort countDownLatch.await() after time out

If you want to stop execution of other threads, if any thread fails - you'll need some additional communication layer.

For example:

AtomicBoolean kill = new AtomicBoolean(false);
CountDownLatch latch = new CountDownLatch(SOME_NUM);

class Task extends Runnable {
     public void run() {
         try {
              ....
              if (kill.get())
                  throw new Exception();
              ....
         } catch (Throwable throwable) {
            kill.set(true);
         } finally {
            countDownLatch.countDown();
         }
     }
}

If you just want to release count down on Throwable, regardless of other processes, you can do countDown in loop on Exception

class Task extends Runnable {
     public void run() {
         try {
              ....
         } catch (Throwable throwable) {
            while(countDownLatch.getCount() != 0)
               countDownLatch.countDown();
         } finally {
            countDownLatch.countDown();
         }
     }
}

You can combine 2 countDown tasks

CountDownLatch A = new CountDownLatch(1);
CountDownLatch B = new CountDownLatch(1);

class CountDownTracker extend Runnable {
     public void run() {
         B.await();
         A.countDown();
     }
}

class Task extends Runnable {
     public void run() {
         try {
              ....
         } catch (Throwable throwable) {
            A.countDown();
         } finally {
            B.countDown();
         }
     }
}

in this case A will finish after completion, or any Task failure.

And so on...

0
Andreas Aumayr On

In addition to the other answers:

it depends on what "but if something fails" means, but if failing means you catch an Exception in a worker thread, you may count down the latch within the catch clause as well. This of course changes the meaning of countDown from "Successfully processed" to "processing complete" - so your code has to handle this..

0
Sergey Shcherbakov On

Check whether your use case allows solving the problem with keyboard interactive input. Instead of CoundDownLatch or Semaphore you could then expect manual input in System.in:

Scanner sc = new Scanner(System.in);
sc.nextLine();

If you need that in unit tests, make sure that your environment is set up to read the user input, e.g. start the IntelliJ Idea with -Deditable.java.test.console=true option in Help -> "Edit Custom VM Options..."