`

How to handle InterruptedException

    博客分类:
  • Java
阅读更多

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.

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.

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

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. ;-)

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.

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.

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

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

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

thierno said...

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

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;
}
}

}
}

分享到:
评论

相关推荐

    JAVA InterruptedException

    在Java编程语言中,`InterruptedException`是一个非常重要的异常类型,主要与线程的中断机制相关。这个异常通常在以下情况抛出:当一个线程正在阻塞(例如等待I/O或者在`synchronized`块中)并且其他线程通过调用`...

    处理 InterruptedException1

    处理 InterruptedException 在 Java 语言中,有很多方法可以抛出 InterruptedException,例如 Thread.sleep() 和 Object.wait()。这些方法都是阻塞方法,它们的完成取决于外部事件,而不是简单地运行完成任务。...

    Java处理InterruptedException异常的理论与实践

    在Java编程中,`InterruptedException`是一个特殊的异常类型,主要用于处理线程中断的情况。当你在代码中调用诸如`Thread.sleep()`, `Thread.join()`, 或 `Object.wait()`等阻塞方法时,如果线程被中断,这些方法会...

    [bugfix]重新理解Thread的InterruptedException

    `Thread`类是Java多线程编程的核心,而`InterruptedException`异常则是与线程中断密切相关的。本文将深入探讨`InterruptedException`异常,以及如何在实际编程中正确处理它。 首先,我们需要了解线程的中断机制。...

    InterruptedException和interrup

    在Java编程语言中,`InterruptedException`是一个非常关键的异常,主要与线程的中断机制相关。这个异常通常在处理线程中断时抛出,当一个线程正在执行时被中断,如果该线程正在阻塞(例如等待I/O或者在`wait()`, `...

    Handle.线程问题

    ### Handle与线程问题 在Android开发中,`Handler`机制是解决子线程与UI主线程通信的关键技术之一。由于Android系统为了确保用户界面的响应性和流畅性,强制所有与用户界面相关的操作都必须在主线程(也称为UI线程...

    java.lang.InterruptedException(解决方案).md

    项目中碰到的,已解决,写个文档记录一下

    cuit大数据实验3 111111111111111

    The experiment aims to implement a data processing task using MAPREDUCE, specifically, to process a log file containing user login records from a social media website. 问题描述 The experiment is ...

    Java检测线程中断状态的方法示例

    在上述示例中,`Thread.sleep(100)`会阻塞当前线程,如果线程在此期间被中断,`sleep()`方法会抛出`InterruptedException`。然而,`InterruptedException`被捕获后,线程的中断状态会被自动清除,除非再次调用`...

    java 一手画方一手画圆 多线程

    The title “java 一手画方一手画圆 多线程” translates to "Java: Drawing Squares and Circles with Multi-Threading." This indicates that the program is designed to draw shapes using two separate threads...

    2D弹性球动画(对初学者很有参考价值)

    catch (InterruptedException e) { } // Ignore interruptions } } /** Start animating when the browser starts the applet */ public void start() { animator = new Thread(this); // Create a ...

    飞机大战java源码

    public static void main String args[] throws InterruptedException { MainFrame mainFrame; try { mainFrame new MainFrame ; mainFrame loadGame ; } catch Exception e { e printStackTrace ; } }...

    java开发飞机大战(可运行)

    public static void main String args[] throws InterruptedException { MainFrame mainFrame; try { mainFram e new MainFrame ; mainFrame loadGame ; } catch Exception e { e printStackTrace ; } } }...

    java用ffmpeg实现MP4转ogg源代码技术方案资料

    } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } ``` 在上面的代码中,我们使用`Runtime.getRuntime().exec()`方法执行FFmpeg命令行。`"-i"`参数指定输入文件,而输出文件路径...

    SCJP 6 question demo

    - **Thread Interruption:** The `wait()` method can throw an `InterruptedException` if the thread is interrupted while waiting. However, the scenario does not involve interruption, so this exception is...

    进度对话框,使用Handler类来不断更新进度对话框

    } catch (InterruptedException e) { e.printStackTrace(); } // 创建并发送消息,消息的what字段作为进度值 Message msg = new Message(); msg.what = i; handler.sendMessage(msg); } // 耗时操作完成...

    java中断线程的正确姿势完整示例.rar

    3. **捕获并处理InterruptedException**:对于那些会抛出`InterruptedException`的方法,我们通常需要在`try-catch`块中捕获它。捕获后,可以清除中断标志(因为这些方法会自动清除),然后根据需要处理中断情况,...

Global site tag (gtag.js) - Google Analytics