开发者

Program continues to run despite InterruptedException

I started learning java and I am开发者_高级运维 now at the concurrency chapter. After reading some stuff about concurrency I tried an example of my own.

public class Task implements Runnable{

public void run() {
    while(!Thread.interrupted()) {
        try {
            System.out.println("task");
            TimeUnit.SECONDS.sleep(2);
        }catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}

}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newCachedThreadPool();
    exec.execute(new Task());
    TimeUnit.SECONDS.sleep(10);
    exec.shutdownNow();
}

The problem is that i was expecting to see the following output:

task
task
task
task
task
interrupted

but after I get this, the program continues printing until I close it.

So, my question is what am I doing wrong? why does the program continues printing?


When you shutdown the executor, it tries to stop its running tasks by interrupting them. This causes an InterruptedException to be thrown, but you just swallow it and continue. You should return in your catch clause, and/or reset the interrupted status of the thread by calling Thread.currentThread.interrupt(), which will reset the interrupted status and exit the loop.


The section about interrupts in the Java tutorials about concurrency explain the problem quite well:

The Interrupt Status Flag

The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking Thread.interrupt sets this flag. When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared. The non-static isInterrupted method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.

So when you catch the InterruptedException within the loop, the interrupted status is already reset and thus, the next call of Thread.interrupted() will return false, which in turn keeps the while loop running. To stop the loop, you have the following options:

  • Use break to exit the loop
  • Use return to exit the whole method
  • Move the try-catch-block to outside the while loop (as suggested by Nathan Hughes)
  • Call interrupt() on the current thread to set the interrupted flag again
  • Use a separate boolean to control the loop and set that flag accordingly in the catch-block
  • Make the task a recurring task by using a ScheduledExecutorService and dropping the loop from the run-method of your Runnable


You're still in the while loop, add a break or some other way out of the loop.

    catch (InterruptedException e) {
        System.out.println("interrupted");
        break;
    }

Threading in Java is kind of a cooperative activity, you've been asked to stop, but you need to be polite enough to actually do it. This allows the thread time to tidy its affairs before its demise.

As is explained in detail by Simon and Amir, your loop termination condition is surprisingly not sufficient.


"There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so if any tasks mask or fail to respond to interrupts, they may never terminate."

source : http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜