How to handle InterruptedException

How to handle InterruptedException?

在线程编程中往往会遇到这个异常,但是我们该怎么处理这个异常呢?今天搜了Google,摘下来:

 

http://www.artima.com/forums/flat.jsp?forum=276&thread=161312

In his latest DeveloperWorks article, Brian Goetz discusses strategies for dealing with InterruptedException. The article shows how swallowing InterruptedException can lead to unpredictable application behavior, and outlines strategies for cancellable tasks as a way to manage this aspect of Java concurrency.

Most developers deal with InterruptedException by simply swallowing it. Brian Goetz in his recent DeveloperWorks article shows why this is wrong:

The worst thing you can do with InterruptedException is swallow it—catch it and neither rethrow it nor reassert the thread's interrupted status. The standard approach to dealing with an exception you didn't plan for—catch it and log it—also counts as swallowing the interruption because code higher up on the call stack won't be able to find out about it. (Logging InterruptedException is also just silly because by the time a human reads the log, it is too late to do anything about it.)

The article explains the notion of a blocking method:

When a method throws InterruptedException ... it is telling you that it is a blocking method and that it will make an attempt to unblock and return early—if you ask nicely... The completion of a blocking method ... is ... dependent on some external event, such as timer expiration, I/O completion, or the action of another thread (releasing a lock, setting a flag, or placing a task on a work queue). Ordinary methods complete as soon as their work can be done, but blocking methods are less predictable because they depend on external events. Blocking methods can compromise responsiveness because it can be hard to predict when they will complete.

A method that calls a blocking method becomes a blocking method as well. The main benefit of InterruptedException is the ability to deal with blocking methods by allowing cancellation of such methods from another thread and then letting the interrupted thread perform cleanup work.

For instance, in a GUI application, the user might be given a chance to interrupt a blocking method, or in a server application a monitoring component can cancel a task given some operational conditions, such as a timeout. When a caller interrupts a blocking method, the blocking method will have an opportunity to perform cleanup work by handling InterruptedException .

If no special cleanup is required, the article suggests that the blocking method should handle InterruptedException by re-interrupting the current thread:

public void run() { 
    try {
        while (true) {
            Task task = queue.take(10, TimeUnit.SECONDS);
                task.execute();
             }
         }
    catch (InterruptedException e) { 
        // Restore the interrupted status
        Thread.currentThread().interrupt();
    }
}

The main reason for doing is that the interruption request that resulted in InterruptedException may have multiple recipients:

The standard thread pool (ThreadPoolExecutor ) worker thread implementation is responsive to interruption, so interrupting a task running in a thread pool may have the effect of both canceling the task and notifying the execution thread that the thread pool is shutting down. If the task were to swallow the interrupt request, the worker thread might not learn that an interrupt was requested, which could delay the application or service shutdown.

What do you think of the article's conclusions? What are your strategies for handling blocking methods, and how do you deal with InterruptedException in your code?

 

http://203.208.37.132/search?q=cache:ZfdrN3gjDEoJ:michaelscharf.blogspot.com/2006/09/dont-swallow-interruptedexception-call.html+How+to+handle+InterruptedException&cd=6&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy28Tiz_OPdS_v5AmbeiF2ZRExDzpSQ

Have you ever written the following code?
try {
    doSomething();
} catch(InterruptedException

 swallowed) {
    // BAD BAD PRACTICE, TO IGNORE THIS EXCEPTION

    // just logging is also not a useful option here....
}

I have! I newer knew what the heck to do with those annoying InterruptedException when I simply wanted to call Thread.sleep(..). What is this InterruptedException ? Why is it thrown? Why can't I ignore it?

Before I explain the whys, here is what you should do (if you don't re-throw):
try {
    doSomething();
} catch(InterruptedException

 e) {
    // Restore the interrupted status
    Thread.currentThread().interrupt()
;

}


What is the InterruptedException ?

There is no way to simply stop a running thread in java ( don't even consider using the deprecated method stop() ). Stopping threads is cooperative in java. Calling Thread.interrupt() is a way to tell the thread to stop what it is doing. If the thread is in a blocking call, the blocking call will throw an InterruptedException , otherwise the interrupted flag of the tread will be set. A Thread or a Runnable that is interruptable should check from time to time Thread.currentThread().isInterrupted() . If it returns true, cleanup and return.

Why is it InterruptedException thrown?

The problem is that blocking calls like sleep() and wait() , can take very long till the check can be done. Therefore they throw an InterruptedException . However the isInterrupted is cleared when the InterruptedException is thrown! (I have some vague idea why this is the case, but for whatever reason this is done, that is how it is!)

Why can't InterruptedException be simply ignored?

It should be clear by now: because ignoring an InterruptedException means resetting the interrupted status of the thread . For example, worker threads take runnable from a queue and execute they may check the interrupted status periodically. If you swallow it the thread would not know that it was interrupted and would happily continue to run.

Some more thoughts
Unfortunately it is not specified that Thread.interrupt() can only be used for cancellation. It can be used for anything that requires to set a flag on a thread. So, ending your task or runnable early might be the wrong choice, if the interrupted status is used for something else. But common practice is to use it for cancellation. But even if it is used for something else, you code does not have the right to reset the interrupt flag (unless you are the owner of the thread).

To learn more read the nice article Dealing with InterruptedException by Brian Goetz.

Or read Java Concurrency in Practice By BriaBrian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, and Doug Lea. It's a great book! If you program in java 5 this book is a must read! . I bought the book after I read Brians artikle. I have not yet read the entire book, but what I have read impresses me. It gives a lot of theorie and options. Very competent and complete, but I'm missing a set of simple patterns for concurrent programming. I'm looking forward to Doug Leas 3rd edition of Concurrent Programming in Java

Summary: If you don't know what to do with an InterruptedException call Thread.currentThread().interrupt()

11 comments:
AlBlue said...

Firstly, .interrupt() does not mean 'quit'. It means, well, interrupt. It's a way of notifying that your thread needs to do something, be it start again, cancel, quit, reiterate, reload config file ... it's basically the same as kill -HUP, which is interpreted in a number of different ways depending on the program.

Secondly, why catch it at all? Propagate the exception upwards. That's good practice for pretty much any exception that you don't know what to do with.

September 18, 2006 9:45 AM
Anonymous said...

Wow - get a clue dude. That is the exactly wrong advice of what to do regarding InterruptedException !!!

Here's the correct answer:

1) DON'T call Thread.currentThread().interrupt()!!! Your thread was already interrupted, which was why you received the InterruptedException in the first place. Why one earth would you want to interrupt it again?!?!? Not to mention that you're telling the thread that was already interrupted to then go and interrupt itself!!!! Duh!

2) If you've coded your thread loops properly with a termination condition (e.g., while (!finished)) then doing nothing when you receive an InterruptedException is a perfectly reasonable thing to do. You told a thread to block on some operation until some condition was met (e.g., it was given some data). However, someone else wants to interrupt the operation before that condition was met. (Most likely a thread shut-down process of some sort.) So your thread gets woken up without its required condition being met. So what? Check whether the thread is supposed to terminate or keep running. If it should terminate (i.e., it's being shut down) then let it exit the thread loop and die. If not, then let it loop again and go back to blocking.

Sheesh! Have some clue what you're talking about before you write something like this in public.

September 18, 2006 3:40 PM
Michael Scharf said...

Alex, I agree, re-trow is the best solution. But there are cases, when you cannot propagate the interrupted exception. In these cases it would get swallowed if you don't re-throw and you don't call interrupt.

But if you don't know what the meaning of the -HUP signal is, you should better not swallow it.

Michael

September 20, 2006 5:20 AM
Michael Scharf said...

Anonymous, good that you are anonymous, because you should maybe read the documentation before you blame me of not understanding what I am talking about.

1) In the documentation of Thread.sleep(long) (as in any other method that throws InterruptedExceptin) it says: "The interrupted status of the current thread is cleared when this exception is thrown".

2) I agree, that it is not reliable to use interrupt to terminate your operation. However, the interrupt flag might mean something to someone outside your scope. By catching the exception and not restoring the interrupted state you are swallowing important information.....

Sheesh! Have some clue what you're talking about before you write something like this in public. ;-)

September 20, 2006 5:29 AM
Virtualwarp said...

There is another solution to handle InterruptedException when you cannot throw it. It's possible to wrap the InterruptedException into a RuntimeExcpetion. This might help in cases where you don't want to interrupt the whole thread.

October 23, 2006 8:50 AM
Villane said...

I think Anonymous is at least partly right. The interrupted status doesn't seem like very reliable information exactly because how many complex scenarios there are that can clear it. For example, one query method also clears it:

"public static boolean interrupted()

Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. ..."

I think it's better to use a custom property for any meaningful thread statuses. Of course, this usually means some kind of common base class or interface for threads, which is also not a great solution.

March 02, 2007 10:33 PM Michael Scharf said...

Villane,

it's true that the Thread.interrupt() is not really reliable, because its not well defined how to use it. But it is the *only* way to terminate a blocking call..

Michael

March 03, 2007 12:38 AM
Anonymous said...

Hello,

I find this discussion very useful. I have coded a garbage collector which runs in a separate thread and removes objects from a cache. The code is as follows:

public void run(){

while (true){
try{
Thread.sleep(SOME_DURATION);
cache.lock.writeLock().lock();
//clean up the cache
cache.lock.writeLock().unlock();
}
catch(InterruptedException ie){
}
}//while
}

I think I am okay with not adding the Thread.currentThread().interrupt() in the catch block because I don't want the garbage collector to be turned off during program execution. I wonder though if the thread could ever be interrupted by some process that has been asked to terminate the thread...for example a program from which you can gracefully shut down a running application. You would not know the source of the InterruptedException . If the code above was interrupted by a program which wants to shut down the thread, then the while loop should be terminated. If some action in the loop caused the interrupt, then the loop should continue, and be given a chance to repeat the action at a later time.

If possible, please let me know the possible sources which would invoke the interrupt and if my concerns are valid.

Thanks so much.

-Paula

September 07, 2007 8:22 PM Michael Scharf said...

Paula,
if you create the thread and you have control over the thread, then you can swallow the exception. You have somehow to define your own mechanism to shut down the thread. If you want to stop the Thread, while it is sleeping for SOME_DURATION, you'd have to call the method Thread.interrupt(). But if you swallow the interrupt you won't get out of your infinite while loop. If you use the interrupt state of your thread as mechanism to shut it down your loop would look like:

while(!isInterrupted()) {
try {
Thread.sleep(SOME_DURATION);
//clean up the cache
} catch(InterruptedException ie){
break;
}
}


But then you should make sure that no code that you call from within the loop is swallowing the interrupt exception. And that is really the problem. Because there is so much code out there that swallows InterruptedException , using the thread interrupt mechanism is not really reliable....


Michael

September 07, 2007 8:44 PM
thierno said...

hello every body.
I would like to know how i could stop my threads with a boolean .

September 17, 2009 3:57 PM
thierno said...

public class myThread implements Runnable{

private Thread T1;

public void Start ( ) {
myThread = new Thread( this );
myThread.start();
}
public void run(){
try{
for (int i=0; i< someThing; i++){
traitement();
Thread.sleep(1000);
}//end for
catch(InterruptedException e){}
}//end try
}//end run

// and this my method to stop threads but i can't stop it. NEED HELP.

boolean finish = true;
synchronise public void stopThread(){
finish = true;
while(finish){
if (T1.isAlive()){
T1.interrupt();
T1 = null;
}
}

}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值