Best practices for handling InterruptedException [duplicate] - java

This question already has answers here:
Handling InterruptedException in Java
(7 answers)
Closed 4 years ago.
In business scenario, InterruptException occurs multiple times, some before the business code is executed, and some after the business code. How to deal with InterruptException makes me confused.
    
1. preBusiness code semaphore.acquire()
try {
semaphore.acquire();
} catch (InterruptedException e) {
// do something
}
resObj = caller.stepTry();
semaphore.release();
postBusiness code latch.await(), service.take().get()
CompletionService<CallableResultBO> service = new ExecutorCompletionService<>(executor);
CountDownLatch latch = new CountDownLatch(size);
for (R callable : listCall){
callable.setCountParam(JdkThreadCountBO.buildByLatch(latch));
service.submit(callable);
}
try {
latch.await();
} catch (InterruptedException e) {
// do something
}
CallableResultBO[] resArr = new CallableResultBO[size];
for ( int i = 0; i < size; i++ ){
try {
resArr[i] = service.take().get();
} catch (InterruptedException e) {
// do something
} catch (ExecutionException e) {
// do something
}
}
There are also some doubts found in practice, and I am still thinking about how to draw conclusions.
     A thread can't be interrupted casually. Even if we set the interrupt state for the thread, it can still get the CPU time slice. Usually only threads blocked by the sleep() method can immediately receive an InterruptedException, so in the case of a sleep interrupt task, you can use try-catch to jump out of the task. In other cases, it is necessary to determine whether the task needs to be jumped out (Thread.interrupted() method) by judging the thread state.
     In addition, the code modified by the synchronized method will not be interrupted immediately after receiving the interrupt signal. The synchronization code of the ReentrantLock lock control can be interrupted by InterruptException.

Generally, you are advised to do the following:
void methodThatWaits()
{
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
So, no, Thread.currentThread().interrupt(); is not redundant.
This is known as the Java Thread.currentThread().interrupt idiom, and it is explained in detail in Java Concurrency in Practice, Chapter 7.1.3. It is also mentioned in Effective Java, you can read an excerpt here: Google Books - Effective Java - search for java idiom thread interrupt interruptedexception josh bloch

All the java.util.concurrent classes use interruption uniformly, to indicate that the receiving thread should wind up what its doing and terminate. It seems to me it only makes sense to follow the same guidelines when writing code that uses these classes.
When something throws InterruptedException the interrupt flag for that thread is cleared. Calling Thread.currentThread().interrupt restores the flag to its previous value.
For toy examples in tutorials restoring the flag seems stupid, because it’s in a catch block at the end of a run method and the thread is terminating immediately anyway. The point is that there may be many layers of things going on within a thread, you may have a Runnable task submitted to a threadpool where that task is talking to a blocking queue, etc., where every participant needs to know if an interrupt occurs so they can all arrive at a stopping point and finish gracefully. If any one of these eats the InterruptedException without restoring the flag, somebody may miss hearing about the interrupt, the thread will keep on working, and your application may not quit cleanly.
Not finishing cleanly can mean:
There may be half-done work hanging out to dry as a result.
Threads are GC roots, so you may get a memory leak.
Any non-daemon thread that stays alive keeps the JVM from exiting.
For what to do with InterruptedException: Synchronizers in java.util.concurrent tend to let it be thrown. Whether you do that or not depends on what you need to do to finish things up. Thread cancellation is voluntary so that you can make sure your task gets cleaned up reliably.

Related

How do I interrupt a thread given a Future object?

I want to start a thread and cancel it if it doesn't finish within 5 seconds:
private final class HelloWorker implements Callable<String> {
public String call() throws Exception {
while(true) {
if (Thread.isInterrupted()) {
return null;
}
}
return performExpensiveComputation();
}
private String performExpensiveComputation() {
// some blocking expensive computation that may or may not take a very long time
}
}
private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Future<String> future = executorService.submit(new HelloWorker());
try {
String s = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("cancelled: " + future.isCancelled() + "done: " + future.isDone());
executorService.shutdown();
try {
System.out.println("try to terminate: " + executorService.awaitTermination(60, TimeUnit.SECONDS));
} catch (Exception ex) {
// ignore
}
}
However it looks like the awaitTermination returns false. Is there a way for me to check why an ExecutorService won't terminate? Can I figure out what threads are still running?
There is no safe way to stop a running thread without disturbing the stability of the rest of the process. This is why Thread#stop has been deprecated a long time ago, and why Executor Services only use the soft, cooperative Thread#interrupt mechanism.
Your thread will have to actively check if an interrupt has been requested and perform proper cleanup before ending. Alternatively, the thread will call some interruptible JDK methods, which will throw InterruptedException, which the tread will properly honor and end itself.
Why Future.cancel() doesn't work the way you think it does
Future cancel removes the task from the running queue. If your task is already running it won't stop it. So cancel() is a different concept that interrupting. As the Javadocs say:
Attempts to cancel execution of this task. This attempt will fail if
the task has already completed, has already been cancelled, or could
not be cancelled for some other reason. If successful, and this task
has not started when cancel is called, this task should never run. If
the task has already started, then the mayInterruptIfRunning parameter
determines whether the thread executing this task should be
interrupted in an attempt to stop the task.
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html#cancel(boolean)
What you are asking is how to interrupt. Fortunately, when you call Future.cancel() it will call the interrupt method. But you'll need to allow it with the mayInterruptIfRunning flag and will need to handle interrupts correctly (see below).
Why interrupt?
Interrupting threads in Java is useful when you have a long running task that you now need to stop, or when you have a daemon that you need to turn off, and other examples.
How to interrupt
To interrupt you call interrupt() on the thread. This is a cooperative process, so your code has to be ready for it. Like this:
myThread.interrupt();
Responsible code
Your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.
Should I use isInterrupted() or interrupted()
You should prefer interrupted() because:
Your code should reset the interrupt flag because if you don't the thread you are using could go back to a thread pool with an interrupted state causing problems (of course, that's a bug in the thread pool code, you won't get that behavior if you use Executors.newFixedThreadPool() for example. But other threading code could have it.
As another answer stated, the clearing of the interrupted flag indicates that you've received the message and are taking action. If you leave it on true, the after a while caller can assume you won't respond to it in a timely manner.
Why interrupt() why not some other flag in my code?
Interrupt is the best mechanism for interruption because our code can be ready for it. If we find code that is just catching and ignoring the InterruptExceptions or not checking for interrupted() in its body then we can correct those mistakes and make our code always cleanly interruptible without creating arcane dependencies on non-standard mechanisms in your code.
Unfortunately Joshua Block proposed the opposite in his famous book Effective Java, Second Edition. But enabling the interrupt() method to work as intended is much better, because this code is used by the Java standard library as explained above. A custom interruption method would not be.

Always call Thread.currentThread().interrupt(); when catching an InterruptedException?

This IBM developerWorks article states:
“The one time it is acceptable to swallow an interrupt is when you know the thread is about to exit. This scenario only occurs when the class calling the interruptible method is part of a Thread, not a Runnable […]”.
I always implemented Runnable for my threads by now. Giving a Runnable implementation like this:
public class View() implements Runnable {
#Overload
public void run(){
Thread worker = new Thread(new Worker());
worker.start();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
worker.interrupt();
// Thread.currentThread().interrupt();
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
Is it really necessary to call Thread.currentThread().interrupt(); right before my return; statement? Doesn’t return; perform a clean enaugh exit already? What’s the benefit of calling it? The article states that it should be done because otherwise “[…] code higher up on the call stack won't be able to find out about it […]”. What’s the benefit of a thread in Thread.State.TERMINATED with interrupted flag set over one without it upon application shutdown? Can you give me an example where code outside the Runnable inspects the interrupted flag for a sensible reason?
BTW, is it a better code design to extend Thread instead of implementing Runnable?
It resets the interrupt flag. This JavaSpecialists newsletter covers this confusing topic in more detail.
In my example, after I caught the InterruptedException, I used
Thread.currentThread().interrupt() to immediately interrupted the
thread again. Why is this necessary? When the exception is thrown, the
interrupted flag is cleared, so if you have nested loops, you will
cause trouble in the outer loops
So if you know that your code is not going to be used by another component, then you don't need to re-interrupt. However I really wouldn't make that minor optimisation. Who knows how your code is going to be used/reused in the future (even by copy/paste) and consequently I would reset the flag for every interrupt.
Here is an example where return it is not enough:
public void doSomething1() {
while (someCondition1()) {
synchronized {
try {
this.wait();
} catch (InterruptedException e) {
return; // Should be Thread.currentThread().interrupt();
}
}
}
}
public void doSomething2() {
while (someCondition2()) {
doSomething1();
}
}
As the exception throw clears the interrupted state next time doSomething1() is executed the status is cleared and the thread does not terminates.
I prefer extending Thread because it gives you a better understanding of what the thread is doing, but it is not necessarily better code design.
As Brian stated ,it resets the interrupt flag but that doesn't say much. In your case it will do nothing and the View-Thread will keep on running.
When interrupting a Thread, the standard procedure is that the Thread should stop running. It won't do this automatically and you have to implement a way to stop it once it is interrupted.
Using the built-in functionality there are two options:
Have the main loop inside the try-block for the InterruptedException. This way, when it is interrupted you you will be thrown out of the loop and the method will exit.
The above can be bad if you have to save the state as it may corrupt the state. As an alternative, you can set the interrupted-flag (as said when it's thrown. re-interrupt it Interrupt the Thread
Either way, you have to check that the Thread is interrupted in your while-loop (with !Thread.currentThread().isInterrupted()-statement in the while-loop) or it may/will not exit. You're not fulfilling one of the first options and neither checking the flag, so your View-thread will keep on running after being interrupted.
Is it really necessary to call Thread.currentThread().interrupt(); right before my return; statement?
As a point, I always do. We all copy-and-paste code and swallowing the interrupt is such a serious problem that I as a rule always do it, even if the thread is about to die.
Doesn’t return; perform a clean enough exit already?
If you are sure that it is the last return before the run() method completes and the thread exits, then yes, it not technically necessary. But see above. For posterity, return; doesn't do anything with the interrupt flag.
The question is whether your View class has been wrapped. Are you sure that when you return you are exiting the Thread. Maybe someone is delegating to it. AOP may be in place to do some sort of instrumentation.
What’s the benefit of calling it? The article states that it should be done because otherwise “[…] code higher up on the call stack won't be able to find out about it […]”.
In general, it is important to not swallow the interrupt when your code is called by some sort of wrapping code (delegation, AOP, etc) which needs the interrupt flag. If you are swallowing it, the wrapper won't be able to use it. But in this case, there is no benefit.
What’s the benefit of a thread in Thread.State.TERMINATED with interrupted flag set over one without it upon application shutdown?
Nothing. Once the thread exits the interrupt state is worthless. And actually, it looks like the interrupt state isn't even persisted after the thread is dead.
Thread thread = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("caught");
}
}
});
thread.start();
thread.interrupt();
System.out.println(thread.isInterrupted());
thread.join();
System.out.println(thread.isInterrupted());
Prints:
true
caught
false
Can you give me an example where code outside the Runnable inspects the interrupted flag for a sensible reason?
I can't. There is no code outside of the thread's run() method unless someone is wrapping your runnable in other code without your knowledge.
This may happen if you are using an ExecutorService but in that case the thread's interrupt status is specifically cleared with a wt.isInterrupted() before the job is run.
So again, the reason is to do is is because it's a good pattern and that's what's important in software engineering.

Differences between synchronized keyword and ReentrantLock [duplicate]

This question already has answers here:
What's the difference between Synchronized and Lock in my example?
(2 answers)
What's the difference in using ReentrentLock and Synchronized(object)? [duplicate]
(1 answer)
Closed 5 years ago.
I made a thread pool based on the example on this page.
In the worker thread we have the infinite loop that never lets the thread die and the wait() method call that pauses the thread when there is no work to do:
while (true) {
synchronized(queue) {
loop:while (queue.isEmpty()) { // labled the loop so we can return here
try
{
queue.wait();
if(queue.isEmpty()) // check the condition predicate again
continue loop;
}
catch (InterruptedException ignored)
{
}
}
r = (Runnable) queue.removeFirst();
}
// If we don't catch RuntimeException,
// the pool could leak threads
try {
r.run();
}
catch (RuntimeException e) {
// You might want to log something here
}
The fact is that r = (Runnable) queue.removeFirst(); can throw a NoSuchElementException which is a RuntimeException if the queue is empty. And when such an exception is thrown on that line, the current thread holding the mutex dies and the pool leaks the thread. The mutex seems to be released when the thread dies.
However, if you instead of using the default synchronized keyword to synchronize the queue, use the ReentrantLock to lock and Condition for signaling and awaiting, the current thread that holds the mutex does not seem to release the lock when it interrupts unexpectedly.
So, in my case, when I checked with JVisualVM under the Threads tab I could see that the AWT-EventQueue-0 thread was wating for Thread-1 to release the mutex. But the Thread-1 died upon its way to run the task and was unexpectedly terminated (RuntumeException) and the mutex did not seem to be released.
My questions:
1) Does not ReentrantLocks being released if the thread that holds it terminates unexpectedly?
2) Is there any difference between while (queue.isEmpty()) { and if (queue.isEmpty()) { in the code snippet above? I cannot see any difference since the thread will wait in both cases. But I think the behaviour it different when using if (like if more than one thread can affect the queue).
EDIT
Java Concurrency in Practice states:
For all these reasons, when you wake up from wait you must
test the condition predicate again, and go back to waiting
(or fail) if it is not yet true. Since you can wake
up repeatedly without your condition predicate being true, you
must therefore always call wait from within a loop, testing
thecondition predicate in each iteration.
Look at my edit in the code above, now the code should be correctly as stated in Java Concurrency in Practice.
1) Does not ReentrantLocks being released if the thread that holds it terminates expectedly?
Lock release only when you call Lock#unlock() explicitly. That why recommend to invoke Lock#unlock() in finally block to prevent deadlocks in your application.
2) Is there any difference between while (queue.isEmpty()) { and if
(queue.isEmpty()) { in the code snippet above? I cannot see any
difference since the thread will wait in both cases. But I think the
behaviour it different when using if (like if more than one thread can
affect the queue).
There, no big differences in particular situation. But using while you guarantee assert in your application, you will not invoke removeFirst() when Queue is empty.
Also, PROS for using while instead of if is spurious wakeups.
notes:
If you are implementing this schema not only for education, consider using BlockingQueue. java.util.concurrent library resolved many multithread problems and in most cases you can build application based on the high level abstractions of java.util.concurrent instead of using low-level techniques such as wait()/notify().
Your code seems too complicated - I would simply write:
while (true) {
synchronized(queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException ignored) {
//don't ignore me please
//you probably should exit the loop and return here...
}
}
r = queue.removeFirst(); //Why use a cast? Use generics instead.
}
}
The only situation where queue.removeFirst() could throw a NoSuchElementException is if it is modified concurrently, which is not possible if all accesses to the queue are made in synchronized blocks.
So find the place where you access the queue without holding the lock on the monitor and you will solve your problem.
The reason why you must call wait within a loop is that wait might wake spuriously (i.e. because wait wakes up does not mean your condition has become true so you need to test it again).
As a side note, if you used a BlockingQueue you would not have to worry about those low level details and you could simply write:
while(true) {
Runnable r = queue.take(); //blocks until queue is not empty
}
Stuff in java.util.concurrent give you more flexibility and things like timed waits and try-lock/acquire methods. Also, synchronized gives you code block, unlike lock.lock()/unlock() pairs. It also tends to be more efficient when there is no contention.
Anyway, when using concurrency, one should definitely look into java.util.concurrent since many problems are solved there already.

Does the finally block execute if the thread running the function is interrupted?

If I have a function with a try/finally section, and the thread running it is interrupted while in the try block, will the finally block execute before the interruption actually occurs?
According to the Java Tutorials, "if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues."
Here's the full passage:
The finally block always executes when the try block exits. This
ensures that the finally block is executed even if an unexpected
exception occurs. But finally is useful for more than just exception
handling — it allows the programmer to avoid having cleanup code
accidentally bypassed by a return, continue, or break. Putting cleanup
code in a finally block is always a good practice, even when no
exceptions are anticipated.
Note: If the JVM exits while the try or catch code is being executed, then
the finally block may not execute. Likewise, if the thread executing
the try or catch code is interrupted or killed, the finally block may
not execute even though the application as a whole continues.
class Thread1 implements Runnable {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("finally executed");
}
}
}
...
t1.start();
t1.interrupt();
It prints - finally executed
In the comments to the answer, #Risadinha asked very valid question about whether code in finally block gets executed if we restore interruption flag inside catch block by calling Thread.currentThread().interrupt().
Here is small code snippet to test:
final SomeContext context = new SomeContext();
Thread thread = new Thread() {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// this code gets executed even though
// we interrupt thread in catch block.
context.value = 9;
}
}
};
thread.start();
thread.interrupt();
thread.join(); // need to wait for thread code to complete
assertEquals(context.value, 9); // values are the same!
SomeContext class code:
class SomeContext {
public volatile int value = 10;
}
Many of Oracle's Java tutorials are helpful (I have answers referencing the guarded blocks page and the SAX introduction), but they are not necessarily authoritative, and some of them have mistakes or are incomplete. The quote referenced in the question conflates interruption with the JVM exiting, which is confusing.
First, thread interruption in Java has nothing to do with OS-level interrupts. Sharing a name creates opportunities for confusion but there is no connection.
Next, JVM exit obviously kills the thread without an opportunity to do any cleanup. If the process dies before the thread has gotten as far as the finally block, too bad. But there's no comparison to interruption. Nothing about interruption prevents finally blocks from completing.
A design principle of interruption is that acting on the interruption requires the cooperation of the thread being interrupted. The thread interrupted responds at its discretion, the interruption doesn't compel the thread to do anything. All calling Thread#interrupt() does is set a flag on the thread. Blocking methods like wait or sleep check the flag to see if they should wake up early. (InterruptedException is a checked exception so you can tell who throws it when, and your Runnable can plan for it.) Also any code can use Thread#isInterrupted() to check whether its thread has had the flag set.
When Thread#sleep() recognizes the interrupted flag is set, it clears the flag before throwing InterruptedException. When your thread catches an InterruptedException it's good manners to restore the flag using Thread.currentThread().interrupt(), just in case there is any other code running in that thread that needs to know about the interruption. This comes into play when you have more complex situations with nested synchronizers where, for instance, some deeply nested component could get its sleep interrupted, letting it stay cleared could prevent higher layers from knowing about the interruption. In a simple toy example like the ones in other answers here, it doesn't matter if the flag is restored or not, nothing checks it again and the thread terminates.
A Thread Interrupt in Java is just setting a flag. It doesn't cause anything special to happen to currently executing code, or affect the flow of control.
If your thread is engaged in, or attempts to enter, an operation that throws InterruptedException, then the exception is thrown from the point where that method is invoked and if it's inside a try block, the finally will execute before the exception leaves just like normal.
The effect of interruption is to throw an InterruptedException the next time a blocking operation occurs (in practice, the next time a method is called that specifies it can throw an InterruptedException), at which point -- as usual -- the normal try/catch execution flow is followed, which does indeed execute the finally block after the try and any applicable catches.
It will execute the same way as with any other exception from the try block, not before the interruption.

Java strange thread termination

I have a system with multiple threads running - my main-thread just checks if there are jobs to be done and if there are some, it calls the sub-threads (notifyAll()) who will execute it. After that, the sub-threads just wait() until there are some new tasks.
Actually, the thread-system is running reliable, but after a longer runtime (3-5h), some sub-threads just die without a warning or an error. They just exit one after another - but again only with a time-range of 2-x hours. I have used jconsole to check this phenomenon, which threads are running and how they just simply disappear.
Furthermore, the main-thread is executing every second, but the sub-threads are mainly wait()ing and are not often used at all (since there are not so many tasks in the test environment).
The only reason I can think of is, that the JVM turns off the sub-threads since they are not often used enough?
I would be very thankfull for your help!
P.S. All threads are not defined as daemons and the main-thread just works fine!
edit
Thanks for your answers, but I actually use this loop.
public void addTask (Task in_task) throws InterruptedException {
synchronized (tasks) {
while (tasks.size() == MAXIMUM_NUMBER_OF_TASKS) {
tasks.wait();
}
tasks.offer(in_task);
tasks.notifyAll();
}
}
I use this loop, so that only some speciall amount of tasks will be executed.
The documentation for Object.wait() says:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
Maybe you didn't follow this advice and got a spurious wakeup or interrupt?
Instead of writing your own multi-threaded task execution solution you could use java.util.concurrent.ThreadPoolExecutor. This would probably be a good idea no matter whether you are able to fix this bug or not.
I recommend using one of the Executors for managing your tasks. There are less chances that you will lose a possible error or exception in one of you sub-threads, so it should help you debug you program. Any exception that happens in a sub-thread will be stored inside the Future object and rethrown as an ExecutionException when you call Future#get().
List<Future<Void>> taskResults = new ArrayList<Future<Void>>();
ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
while(!finished){
//say you wait (blocking) for a new task here
Callable<Void> task = getNextTask();
//put the task into the pool
Future<Void> result = es.submit(task);
taskResults.add(result);
}
//3 hours later, set `finished` to true
//at the end check that no exceptions were thrown
for(Future<Void> result : taskResults){
try{
result.get();
}catch(ExecutionException e){
//there was an error
e.getCause().printStackTrace();
}catch(InterruptedException e){
//irrelevant
}
}
In general, stuff in the java.util.concurrent helps you write much more robust multi-threaded applications, without having to resort to Object#wait() and other concurrency primitives (unless you are learning, of course).
Try setting an uncaught exception handler on each thread.
There is a setUncaughtExceptionHandler() function on the Thread. Implement the UncaughtExceptionHandler interface and print the exception.
General idea, but don't do it with anonymous classes/methods:
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
e.printStackTrace();
}
});

Categories

Resources