WHY does Thread.sleep() clear the interrupted flag

2020-02-12 17:36发布

I know that some Thread methods clear the interrupted flag (e.g. sleep, wait, ...). But why do they do this? What is the reason for it?

2条回答
你好瞎i
2楼-- · 2020-02-12 17:56

In short, because those methods send the thread into a "fresh" waiting state (after it was interrupted back into a running state). The previously set "interrupted" flag no longer applies, as the thread has not been interrupted since entering the new waiting state.

查看更多
Ridiculous、
3楼-- · 2020-02-12 18:01

That is a result of interruption being designed not to be totally synonymous with cancellation. The guidance from Oracle is to use interruption only for cancellation, but that view may have been arrived at over time. In any event the design doesn't force that. You can design a task to respond to interruption, then go back to what it was doing.

In Java Concurrency in Practice, 7.1, page 138, it says:

There is nothing in the API or language specification that ties interruption to any specific cancellation semantics, but in practice, using interruption for anything but cancellation is fragile and dfficult to sustain in larger applications.

The way it was designed there is exactly one thing at any given time, either the InterruptedException being caught or the interrupt flag, to tell what the status of the thread is. If the InterruptedException is in-flight the value of the flag is irrelevant. And the idea seems to have been that the code catching the exception should decide whether the interrupted flag should be set or not.

This way it's convenient to use the InterruptedException to exit a loop:

try {
    while (!Thread.currentThread().isInterrupted()) {
        Thread.sleep(5000);
        // ... do stuff ...
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

Here the thread stops looping since the exception is caught outside the loop, it only matters to any surrounding code whether the interrupt flag is set or not. However, if you catch the InterruptedException within the loop, like:

while (!Thread.currentThread().isInterrupted()) {
    // ... do stuff ...
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

(and a lot of code does this, because programmers have had it pounded into their heads that they should never ever even think about using exceptions for flow control), then you have to set the interrupted flag.

I think the intention is that the application developer should use the exception to escape the context of the interruption, eating the exception close to the source does not work as cleanly.

查看更多
登录 后发表回答