try {
for (final Future<Boolean> bool : threadPool.invokeAll(tasks)) {
if (!bool.get()) {
return false;
}
}
return true;
} finally {
threadPool.shutdownNow();
threadPool.awaitTermination(
IMPORT_THREADS_AWAIT_TERMINATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
}
Assume the task can throw an exception. Say there are 5 tasks, and the 5th task throws an exception, but the 1st task in the loop returns false. ( and loop breaks). If that task throws an exception, I want to catch it and do some cleanup logic. I am wondering my logic will never capture exception thrown by task 5 since i break from the loop on task 1
In such a case, will we ever encounter exception thrown by task 5 ?
Show threadPool.shutdownNow() throw the exception of task 5 ?
The exception will be thrown by task5, but the executor will catch it and wrap it as ExecutionException.
In this case, unless you call futureOfTask5.get(), the exception will not be re-thrown.
You can add try...catch block in the call method of task5 to log it.
Related
I am trying to call cancel on CompletableFuture.
It seems from the docs:
If not already completed, completes this CompletableFuture with a CancellationException. Dependent CompletableFutures that have not already completed will also complete exceptionally, with a CompletionException caused by this CancellationException.
That it should complete them exceptionally which is what I was expecting but instead, it throws and immediate CancellationException.
Here is a sample code
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Line 7.
f.join();
With a repro : https://www.mycompiler.io/view/2v1ME4u
Exception in thread "main" java.util.concurrent.CancellationException
at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
at Main.main(Main.java:7)
Line 7 is the f.cancel(true); line.
It doesn't actually throw immediately.
Calling f.cancel(true) causes a CancellationException to be created, capturing the stack trace of the call to cancel. So the stack trace (which is printed because it's unhandled) contains the line of the f.cancel(true); call.
But that exception isn't actually thrown until f.join():
Returns the result value when complete, or throws an (unchecked) exception if completed exceptionally
...
Throws:
CancellationException - if the computation was cancelled
You can see this by putting in a few more print statements into your example code:
CompletableFuture<?> f = CompletableFuture.supplyAsync(() -> false);
f.cancel(true); // Line 8.
try {
f.join();
} catch (CancellationException e) {
System.out.println("CancellationException was thrown at call to f.join()");
e.printStackTrace(System.out);
}
Output:
CancellationException was thrown at call to f.join()
java.util.concurrent.CancellationException
at java.base/java.util.concurrent.CompletableFuture.cancel(CompletableFuture.java:2396)
at Main.main(Main.java:8)
This is what I'm doing:
Stopwatch stopWatchToCheckTimeout;
void checkShutDown() throws InterruptedException {
if (stopWatchToCheckTimeout.elapsed() >= MAX_GRACEFUL_TIMEOUT_DURATION) {
throw new InterruptedException("Time to shut down now!");
}
}
public Void mainFancyMethod() {
try {
while(true) {
checkShutDown();
// do fancy work
}
} catch (InterruptedException ex) {
log.debug("Shutting down gracefully");
}
return null;
}
From the java/lang/InterruptedException documentation its not clear to me if by standards it should be another thread that should interrupt or if its okay for a thread to throw this exception for itself?
Whats the best exception to throw for this use-case?
It seems like you are using exceptions in place of control flow. Is there any reason you couldn't just have checkShutDown return a boolean?
boolean timedOut() {
return (stopWatchToCheckTimeout.elapsed() >= MAX_GRACEFUL_TIMEOUT_DURATION)
}
It is correct for a thread to throw an interrupted exception, and in fact threads are usually the sources of InterruptedException.
In your case, I don't think it's appropriate because it has nothing to do with interruption, which is an established thread state. You just want to exit the execution, which could be done in more graceful and performant ways.
TimeLimitExceededException: https://docs.oracle.com/javase/7/docs/api/javax/naming/TimeLimitExceededException.html
From the Docs: "This exception is thrown when a method does not terminate within the specified time limit. This can happen, for example, if the user specifies that the method should take no longer than 10 seconds, and the method fails to complete with 10 seconds. "
This sounds like just what you are after, or?
In the example you posted, you should not throw an InterruptedException.
The Javadoc for InterruptedException states: Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Being interrupted is a result of Thread.interrupt() being called on your running thread, which is not what's happening in the code you posted.
If you do still want to use an exception to break out of your loop, you should use some other exception type. However, an alternative would be to make your check method return true/false, and use that for the condition of your while loop. So instead of this:
try {
while(true) {
checkShutDown();
// do fancy work
}
} catch (InterruptedException ex) {
log.debug("Shutting down gracefully");
}
do something like this:
while (checkIfSafeToContinue()) {
// do fancy work
}
My intuition is that the following code is wrong. I believe because join() is being used, any exceptions throw while completing the futures will be unchecked. Then when get() is called, there will be no checked exceptions, no logging of any errors, and difficulty diagnosing errors during failure.
List<CompletableFuture> list = ImmutableList.of(future1, future2);
CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()])).join();
try {
result1 = future1.get();
result2 = future2.get();
} catch (InterruptedException | ExecutionException e) {
// will this ever run if join() is already called?
}
I have looked through the documentation for CompletableFuture but haven't found the exact answer to my question. I am asking here and will then go read through the source code.
The only why I can see that the catch block code would run is if somehow checked exceptions can be saved in some execution context and not thrown in join() (or thrown wrapped by an unchecked exception), and then throw again in some form after get(). This seems unlikely to me.
So my ultimate question is, will the catch block code ever run?
Both the join and the get method are blocking method that relies on completion signals and returns the result T. Processing the piece of code as in question :-
On one hand, InterruptedException could be thrown while the thread is interrupted in the process of waiting as we do a get, the wait here is already completed by the join method.
Also, as stated in the join method documentation
/**
* ... if a
* computation involved in the completion of this
* CompletableFuture threw an exception, this method throws an
* (unchecked) {#link CompletionException} with the underlying
* exception as its cause.
*/
So, on the other hand, the ExecutionException for futureN.get() in your case could only be thrown when and if the future completed exceptionally. Since the future if executed exceptionally would end up in throwing a CompletionException for the join call, it wouldn't reach the catch block ever or for that sake try block either.
Yes, the code would never be reached, but that doesn't make the "code wrong".
First, let's just try it out...
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
}
catch (Exception e1)
{
System.out.println("I'd exit here."); // *1
}
try
{
future1.get();
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Entered!");
}
Since you didn't do the try/catch "*1", the Exception would cause the method to exit and the get() would never be reached; so the second catch clause would never be executed.
However, the catch is still necessary because it's for the compiler, which has no way of knowing the previous call sequence.
The more straightforward way of doing this would be like this anyway:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
throw new IllegalArgumentException();
});
try
{
CompletableFuture.allOf(future1).join();
future1.get();
}
catch (CompletionException e1) // this is unchecked, of course
{
System.out.println("Exception when joining");
}
catch (InterruptedException | ExecutionException e)
{
System.out.println("Exception when getting");
}
The javadoc for ExecutorService sometimes refers to the case when a Thread terminates 'due to failure'. However, it is not clear what kind of failure does this refer to.
For instance, the single thread executor documentation says that
if this single thread terminates due to a failure during execution
prior to shutdown, a new one will take its place if needed to execute
subsequent tasks
I would have thought that this situation might happen in case of an Exception, or maybe a RuntimeException, but it does not seem to be the case. Running the following code seems to be giving the same thread name and thread ID.
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
System.out.println("Hello from " + Thread.currentThread().getName()+ " " + Thread.currentThread().getId());
throw new NullPointerException("Test");
});
executor.submit(() -> {
System.out.println("Hello 2 from " + Thread.currentThread().getName() + " " + Thread.currentThread().getId());
});
The output of this code is:
Hello from pool-1-thread-1 12
Hello 2 from pool-1-thread-1 12
It seems that the same thread is being reused even in the case of NullPointerException.
So what kind of 'failure' is the Javadoc referring to?
This is an interesting question. Following the code in ThreadPoolExecutor the thread is discarded when a Runnable is passed to the execute() method.
When you call submit() the executor creates a wrapper for the callable/runnable of type FutureTask. FutureTask.run() has some logic to catch exceptions and store them (so then, you can query this from the Future). In this case, the exception never reaches the ThreadPool, so the thread is not discarded.
Augusto is right. Runnable tasks should have discarded the Thread after encountering the exception when they have passed as parameter in execute() method.
I have found concrete evidence regarding swallowing of exceptions by Future tasks at this article and Future Task source code
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}
There are few more interesting questions in SE around this topic.
Catching thread exceptions from Java ExecutorService
Choose between ExecutorService's submit and ExecutorService's execute
EDIT:
Thread failure or termination will happen when an exception is uncaught in the thread code. If you submit task by execute() instead of submit(), exception won't be caught unless you catch the exception. Uncaught exception by the thread code will result thread to terminate or failure and new thread will be created by Executor.
If you submit the task through submit(), a FutureTask will be created and that task will swallow uncaught exception by the code. Since the exception was caught in FutureTask, the thread won't be discarded.
Have a look at the following snippet with the comments :
try {
Thread.sleep(20000); // Foo thread sleeps for 20 seconds
System.out.println("After the sleep statement");
} catch(Exception exc) {
exc.printStackTrace();
}
// It has been 12 seconds since the thread went to sleep and....I interrupt
Foo.interrupt(); // exception gets thrown and the code in the catch block gets executed
Is there any way I can execute the next statement after the sleep statement ? I want to awaken the thread at some time and want it to continue it work . Is there any thought/method for this ?
Not sure if this is what you want?
try {
Thread.sleep(20000); // Foo thread sleeps for 20 seconds
System.out.println("After the sleep statement");
} catch(InterruptedException exc) {
System.out.println("Sleep was interrupted");
} catch(Exception exc) {
exc.printStackTrace();
}
sleep() throws InterruptedException when it is interrupted. So "Sleep was interrupted" will be printed on interrupt() while "After the sleep statement" is called only if sleep() managed to sleep configured 20 seconds.
If you don't care whether sleep() returned normally or thrown and just continue your work, wrap it with empty try-catch:
public void interruptibleSleep(long millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException exc) {}
}
and then instead of Thread.sleep(20000) call interruptibleSleep(20000):
interruptibleSleep(20000);
System.out.println("After the sleep statement");
I think you're confused. Here's what happens
public void run() {
// This executes as soon as the thread is run
try {
// We decide to sleep for UPTO 20 seconds
Thread.sleep(20000);
// Code here executes ONLY if we managed to sleep for 20 seconds without
// interruption
} catch(InterruptedException exc) {
// Code here executes ONLY if we were interrupted
} catch(Exception exc) {
// This shouldn't ever execute in theory
}
// Code here ALWAYS executes after the sleeping (and ONE of the two blocks)
// whether or not it was interrupted.
}
There is a very well phrased paragraph at The Java Tutorials
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. This is the usage emphasized in this lesson.
Stopping and staring threads reliably is an important part of designing concurrent applications. And even though you could repurpose interrupts to do whatever you want, your code will be more reliable and easier to maintain for others if you leave interrupt for it's most common purpose - requesting that the thread exit. This is something you will probably want to do if the user decides to shutdown the app before the 20 second timeout is finished.
So how to solve the original problem - allowing one thread to indicate to another that it is time to get to work. The class below shows how a CountDownLatch might be used to solve this problem.
The new Foo:
class Foo extends Thread
{
CountDownLatch latch = new CountDownLatch(1);
#Override
public void run()
{
try
{
boolean early = latch.await(20, TimeUnit.SECONDS);
System.out.println("Doing work " + (early ? "right away" : "after delay"));
// do real work here...
}
catch (InterruptedException e)
{
System.out.println("Interrupt detected. Exiting thread...");
}
}
public void goAhead()
{
latch.countDown();
}
}
We get rid of the "Sleep" and replace it with a call to the await method of the latch object. To make foo do work, invoke:
foo.goAhead(); // prints out "Doing work right away"
This causes the latch to countdown. The call to "await" will immediately exit without throwing an exception and returning true.
To shut down foo, use:
foo.interrupt(); // prints out "Interrupt detected..."
This will cause await to throw an InterruptedException just like sleep.
Or do nothing. The call to await times out after 20 seconds, does not throw an exception and returns false. Foo prints out "Doing work after delay"
One long term advantage of this design as that while you are "doing work" you may need to call other blocking methods. Interrupt can still be used to interrupt any of them and help you on your way to shutting down the thread reliably in response to unexpected events.