In Effective Java (page 275), there is this code segment:
...
for (int i = 0; i < concurrency; i++) {
executor.execute(new Runnable() {
public void run() {
ready.countDown();
try {
start.await();
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.countDown();
}
}
}
...
What's the use of catching the interrupted exception just to re-raise it? Why not just let it fly?
The simple answer is that InterruptedException is a checked exception and it is not in the signature of the Runnable.run method (or the Executable.execute() method). So you have to catch it. And once you've caught it, calling Thread.interrupt() to set the interrupted flag is the recommended thing to do ... unless you really intend to squash the interrupt.
Sometimes you can't ignore exception and you must catch it. Mainly this happens when you override method which can't throw InterruptedException in accordance with its signature. For example, this approach is usually used in Runnable.run() method.
The executor can interrupt tasks if they are cancelled but it clears the interrupted flag between tasks to avoid one cancelled task interrupting an unrelated task.
As such, interrupting the current thread here would be dangerous if it actually did anything.
A simpler way around this is to use Callable or ignore the interrupt.
Additionally it is a good idea to catch and log any error or exception thrown in the try/catch block otherwise the exception/error will be discarded and your program could be failing but you won't know it is or why.
Related
I try to stop a thread using .interrupt() method.
Here is my code:
#Override
public void run() {
try {
for (int i = 0; i < 1000000000; i++) {
System.out.println(threadName + " generated " + i);
if (counter.isInterrupted()) {
counter.join();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
What I do not understand is that instead of this code:
if (counter.isInterrupted()) {
counter.join();
}
If I throw an InterruptedException it works as well.
if (counter.isInterrupted()) {
throw new InterruptedException();
}
What I do not understand is why I would choose one instead of another one. Also I've seen some approaches where people use an volatile boolean variable too. Is is safer than my approach?
An InterruptedException is meant to indicate that the current thread has been interrupted in the course of an operation. The issue with your second option is that you are throwing the exception on the basis of some other thread being interrupted. This will cause the wrong impression to be made by calling code.
As a rule of thumb, when you catch an InterruptedException, you should do one of three things:
Rethrow it (without a wrapper exception), so that callers know of the interruption
Re-set the interrupt(), so that the fact that this thread was interrupted is maintained
Handle the interruption (usually by cleaning up and shutting down the thread)
I've used Thread.sleep for all kinds of different reasons, but one thing I've never understood is when an exception would occur during this try /catch block:
try {
Thread.sleep(1000); // sleep for 1 second.
} catch (Exception x) {
fail("Failed due to an exception during Thread.sleep!");
x.printStackTrace();
}
What would have to occur within the computer to actually hit an exception on Thread.sleep? My best guess, would be that maybe the system clock has a once in a lifetime "skip of a beat" like a heartbeat, but how often does this happen..
So in essence, my question is: When executing Thread.sleep, what would have to occur internally for #sleep to throw an exception?
If you look in the JavaDoc for Thread.sleep() you see exactly what might happen:
Throws:
IllegalArgumentException - if the value of millis is negative
InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
An example on how to interrupt another thread might look like this:
public class Foo {
public static void main(final String[] args) throws Exception {
Thread sleepThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Interrupted!");
}
}
});
sleepThread.start();
Thread.sleep(500);
sleepThread.interrupt();
}
}
This will print
Interrupted!
The Thread class defines an interrupt method. When it's called (obviously from another thread) by a thread and there's no security exception, an InterruptedException is thrown.
The purpose is, precisely (and normally), to interrupt the sleep.
Thread.sleep(someValue) can fire InterruptedException.
More info about handling this exception and reson for this you can find here.
You can find a lot usefull answers on SO. Here is the one for example:
When does Java's Thread.sleep throw InterruptedException?
When a thread interrupt is issued, for example if a signal was sent to shut the JVM down.
The Thread can throw an InterruptedException (which you should use instead of general Exception) when the Thread is interrupted (usually by the interrupt() method called from another Thread) instead of just waiting. It has nothing to do with the sleep() method.
Assume that I have the following code:
while(!Thread.currentThread().isInterrupted()){
//do something
Thread.sleep(5000);
}
Now Thread.sleep throws `InterruptedException so it should be like this:
while(!Thread.currentThread().isInterrupted()){
//do something
try{
Thread.sleep(5000);
} catch(InterruptedException e){
}
}
If I hit the catch will the while loop continue or do I need to do Thread.currentThread().interrupt()? If I do call this method, won't that also cause an InterruptedException? Otherwise how I got the exception in the first place?
Also if I have:
while (!Thread.currentThread().isInterrupted()){
//do something
callMethod();
}
private void callMethod(){
//do something
try {
Thread.sleep(5000);
} catch(InterruptedException e){
}
}
again will my while loop break?
Actually your question is more about try - catch - finally than about multithreading.
1) If sleep throws an Exception, the catch block will execute and then the while loop continues.
2) You do the exact same thing as in 1)
To leave the while loop, do:
try{
while(!Thread.currentThread.isInterrupted){
//do something
Thread.sleep(5000);
}
}
catch(InterruptedException e){
}
In that case, if an Exception is thrown, the while loop is left and the catch block is executed.
Calling interrupt on a thread does not in itself throw an exception. Sleeping or waiting while the interrupt flag is set is what causes InterruptedException to be thrown.
It is totally predictable what can throw InterruptedException, so that the thread being interrupted has control and it can choose how to respond. It's a checked exception so it's evident what throws it. It is not like ThreadDeath, which can be thrown anywhere.
When an InterruptedException is thrown the thread's interrupted status is reset. If you want to restore the thread's interrupted status, because you want to check the flag later and have it be true, call Thread.currentThread().interrupt() in order to set it.
Nothing out of the ordinary happens during interruption to change how instructions get processed. So if you choose to catch the InterruptedException in a loop and check the flag to get out, you will need to reset the flag:
while(!Thread.currentThread().isInterrupted()){
//do something
try{
Thread.sleep(5000);
} catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
Alternatively you can use the InterruptedException to get out of the loop:
try {
while (!Thread.currentThread().isInterrupted()) {
// do something
Thread.sleep(5000);
}
} catch (InterruptedException e) {
// flag value is not used here, but still good style
Thread.currentThread().interrupt();
}
If this last snippet is the whole run method of the thread being interrupted, you can get by without setting the interrupted status again, but if you have components being used by other parts you don't want one badly-behaved part to squelch the interrupted flag so that other code in the thread is not aware of the interruption.
Thread.sleep() will clear the "interrupted status" before throwing InterruptedException. You need to call Thread.currentThread().interrupt() in the catch block, otherwise the while condition will most likely not succeed, because the thread will always be "not interrupted" when callMethod returns.
The exception is not caused by the interrupt() method, but by sleep() blocking on a thread that has been signaled as "interrupted". This is explained in more detail here. See also this answer.
Seems to be that this method is takes in an array of threads, then determines if they have completed using InterruptedException, which seems plausible to me.
private static void waitUntilAllThreadsFinished(Thread[] threadArr) {
for(int i=0; i<threadArr.length; i++) {
try {
threadArr[i].join();
} catch (InterruptedException e) { }
log.debug("thread ["+threadArr[i].getName()+"] have completed");
}
}
If you just want to know if the thread has been interrupted , the use public boolean isInterrupted() method on the thread reference. This code is trying to block the current thread on each of the thread's completion, and retrying if it got interrupted in th meanwhile.
I think getState is more appropriate
I would not force the throw and catch, since it is not free of cost. The Thread class have methods to access the current state of an instance.
This code does not just determine whether all threads have completed, but waits for all of them to complete. And it's not using InterruptedException to do this. If join() calls on finished (dead) thread, the code just continues on without exception.
But it will work, I guess...
Why invoke the method Thread.currentThread.interrupt() in the catch block?
This is done to keep state.
When you catch the InterruptedException and swallow it, you essentially prevent any higher-level methods/thread groups from noticing the interrupt. Which may cause problems.
By calling Thread.currentThread().interrupt(), you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.
Java Concurrency in Practice discusses this in more detail in Chapter 7.1.3: Responding to Interruption. Its rule is:
Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests.
I think this code sample makes things a bit clear.
The class which does the job :
public class InterruptedSleepingRunner implements Runnable {
#Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
// You are kidding me
System.out.println(i + " " + i * 2);
// Let me sleep <evil grin>
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
} else {
sleepBabySleep();
}
}
}
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
The Main class:
public class InterruptedSleepingThreadMain {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new InterruptedSleepingRunner());
thread.start();
// Giving 10 seconds to finish the job.
Thread.sleep(10000);
// Let me interrupt
thread.interrupt();
}
}
Try calling interrupt without setting the status back.
Note:
http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
How do I stop a thread that waits for long periods (e.g., for input)?
For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows, because it is not always possible to rethrow the exception. If the method that catches the InterruptedException is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:
Thread.currentThread().interrupt();
This ensures that the Thread will reraise the InterruptedException as soon as it is able.
I would consider it a bad practice or at least a bit risky.
Usually higher level methods do not perform blocking operations and they will never see InterruptedException there. If you mask it in every place you perform interruptible operation, you will never get it.
The only rationale for Thread.currentThread.interrupt() and not raising any other exception or signaling interrupt request in any other way (e.g. setting interrupted local variable variable in a thread's main loop) is the situation where you really can't do anything with the exception, like in the finally blocks.
See Péter Török's answer, if you want to better understand implications of the Thread.currentThread.interrupt() call.
Refer from java doc
If this thread is blocked in an invocation of the wait(), join(),
sleep(long), then its interrupt status will be cleared and it will
receive an InterruptedException.
If this thread is blocked in an I/O operation, the thread's interrupt
status will be set, and the thread will receive a
ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt
status will be set and it will return immediately from the selection
operation.
If none of the previous conditions hold then this thread's interrupt
status will be set.
So, if you change the sleepBabySleep() method in #Ajay George Answer to I/O operation or just a sysout, you don't have to set the status back to stop the program. (BTW, they don't even throw InterruptedException)
Just like #Péter Török said => This is done to keep state. (And particular for method that will throw InterruptedException)