I have a scenario where I want one thread to do some looped operations and second (main) thread to do some other cyclic work while first thread is still doing its job.
My idea was to use CountDownLatch
and await until it is finished in the main thread:
public void process() {
CountDownLatch countDownLatch = new CountDownLatch(10_000);
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> {
for (int i = 0; i < 10_000; i ) {
// do some stuff
countDownLatch.countDown();
}
});
try {
while (!countDownLatch.await(5, SECONDS)) {
// do some other stuff...
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
The problem is sometimes an exception can be thrown in the first (future) thread and in such case it doesn't make sense to continue executing the code in the main thread as well.
I was thinking about assigning the reference of such exception (thrown from the first thread) to volatile field and doing a null check on this field in main's thread loop to see if it should continue looping:
private volatile Exception innerException;
public void process() {
CountDownLatch countDownLatch = new CountDownLatch(10_000);
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> {
try {
for (int i = 0; i < 10_000; i ) {
// do some stuff
countDownLatch.countDown();
}
} catch (Exception e) {
this.innerException = e;
throw e;
}
});
try {
while (!countDownLatch.await(1, SECONDS)) {
// do some other stuff... but it doesn't make sense to continue
// if 'future' has thrown an exception, so let's rethrow it:
if (innerException != null) {
throw innerException;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("Something bad happened in the 'future'! : ", e);
}
}
I'm wondering if this is a good (safe?) idea or maybe there are some better ways to solve that kind of problem?
Appreciate any help on this one, thanks!
CodePudding user response:
You can synchronize on the completion of the future using future.get. If the Runnable/Callable throws an exception, the future.get will throw an ExecutionException. You can get rid of the CountDownLatch completely.