From multiple articles around the internet it's advised not to swallow InterruptedException
. It makes much more sense to do it with thread pool executors something like this when I'm going to reuse the same thread.
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(() -> {
printNumbers(); // first call
printNumbers(); // second call
});
Thread.sleep(3_000);
executor.shutdownNow(); // will interrupt the task
executor.awaitTermination(3, TimeUnit.SECONDS);
}
private static void printNumbers() {
for (int i = 0; i < 10; i++) {
System.out.print(i);
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // preserve interruption status
break;
}
}
}
Code sample above from DZone.
But in the case of creating new thread each time like:
Object LOCK = new Object();
public void doSomeJob() {
myThread = new Thread(new Runnable() {
public void run() {
try {
synchronized(LOCK) {
System.out.println("Inside run");
LOCK.wait();
}
} catch(InterruptedException ignored){}
}
}
}
Do I still need to call Thread.currentThread().interrupt();
? Will that make any sense?
Good references:
https://codepumpkin.com/interrupt-interrupted-isinterrupted-java-multithreading/
http://michaelscharf.blogspot.com/2006/09/dont-swallow-interruptedexception-call.html
In Java Threads, if any thread is in sleeping or waiting state (i.e. sleep() or wait() is invoked), calling the interrupt() method on the thread, breaks out the sleeping or waiting state throwing InterruptedException.
currentThread(). interrupt() , you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.
currentThread() method returns a reference to the currently executing thread object.
Furthermore, calling the interrupted method resets the "interrupted" status of the thread. On the other hand, the isInterrupted method is an instance method that you can use to check whether any thread has been interrupted. Calling it does not change the "interrupted" status of its argument.
Calling the interrupt () method on an instance of a Thread sets the interrupt status state as true on the instance. Use interruption to request a task, running on a separate thread, to finish. In the implementation of requirement 7, InterruptedException is being handled by breaking out of the loop and thus finishing the task early.
One thread cannot call Thread.Sleep on another thread. Thread.Sleep is a static method that always causes the current thread to sleep. Calling Thread.Sleep with a value of Timeout.Infinite causes a thread to sleep until it is interrupted by another thread that calls the Thread.Interrupt method on...
Calling the start () method on a thread puts it in the RUNNABLE state. Threads in this state are either running or ready to run. When a thread is waiting for a monitor lock and is trying to access code that is locked by some other thread, it enters the BLOCKED state.
The thread should catch the ThreadInterruptedException and do whatever is appropriate to continue working. If the thread ignores the exception, the runtime catches the exception and stops the thread. If the target thread is not blocked when Thread.Interrupt is called, the thread is not interrupted until it blocks.
I will give an answer based on section 7.1.2 of great book Concurrency in Practice by Brian Goetz.
In your first example you use ExecutorService
. ExecutorService
manages it's own threads. You are not the owner of those Threads so you do not know what interruption means to them ( for example ThreadPool might choose to kill Threads that were interrupted and create new ones). That is why you should preserve interruption status when you submit a cancelable task to this pool. This citation applies to this case:
Tasks do not execute in threads they own.They borrow threads owned by a service such as a thread pool. Code that doesn't own the thread (for a thread pool, any code outside of the thread pool implementation) should be careful to preserve the interrupted status so that the owning code can eventually act on it, even if the "guest" code acts on the interruption as well. (If you are housesitting for someone, you don't throw out the mail that comes while they're away - you save it and let them deal with it when they get back, even if you do read their magazines.)
In the second case you manage an instance of Thread manually. So you are the owner of it. Therfore you decide what interruption means to this Thread and you do not have to preserve the Interruption Status in the second case if you do not want to apply any Thread Interruption Policy for it :
What you should not do is swallow the
InterruptedException
by catching it and doing nothing in the catch block, unless your code is actually implementing the interruption policy for a thread
Note also that Thread Interruption Policy is different than Task Cancellation Policy :
ThreadPool
might kill Thread that was interrupted and create a new one). It is defined by the owner of the thread.InterruptedException
. Or you can check the interruption flag of the Thread by calling Thread::isInterrupted
(for example in a loop). The implementor of the task chooses how to handle this.Also you should not take any assumptions of Thread Interruption Policy (if you are not the owner of the Thread
). That is why preserving Interruption Status or rethrowing InterruptedException
is considered a good practice.
If your lock comes from java.util.concurrent.locks.Lock
and is interruptible (using .lockInterruptibly()
), it does make sense to interrupt the process so everything might be interrupted and cancelled.
Read chapter Implementation Considerations
from the documentation.
But if your lock is non-interruptible
(using .lock()
) it will not make sense as you won't be able to interrupt the lock.
In your case, you're using wait()
which is interruptable as written here, and will throw an InterruptedException
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With