java.lang.Thread.interrupt()做什么?

你能解释一下调用java.lang.Thread.interrupt()时做什么吗?

170490 次浏览

Thread.interrupt()设置目标线程的中断状态/标志。然后在目标线程中运行的代码可以轮询中断状态并适当地处理它。一些阻塞的方法,如Object.wait(),可能会立即使用中断状态并抛出适当的异常(通常是InterruptedException)。

Java中的中断不是先发制人的。换句话说,两个线程必须合作才能正确地处理中断。如果目标线程没有轮询中断状态,中断将被有效地忽略。

轮询通过Thread.interrupted()方法进行,该方法返回当前线程的中断状态并清除中断标志。通常,线程可能会做一些事情,例如抛出InterruptedException。

EDIT(来自Thilo评论):一些API方法内置了中断处理。在我的头顶,这包括。

  • Object.wait()Thread.sleep(),和Thread.join()
  • 大多数java.util.concurrent结构
  • Java NIO(但不是Java .io),它不使用InterruptedException,而是使用ClosedByInterruptException

编辑(从@thomas-pornin的答案到同样的问题的完整性)

线程中断是轻推线程的一种温和方式。它用于给线程一个退出干净利落地的机会,而不是Thread.stop(),后者更像是用突击步枪射击线程。

如果目标线程一直在等待(通过调用wait(),或其他本质上做同样事情的相关方法,如sleep()),它将被中断,这意味着它停止等待它正在等待的东西,而是接收一个InterruptedException。

完全由线程本身(调用wait()的代码)决定在这种情况下做什么。它不会自动终止线程。

它有时与终止标志结合使用。当被中断时,线程可以检查这个标志,然后关闭自己。但这只是惯例。

什么是中断?

中断是a的指示 线程应该停止它是什么 做和做别的事情。由 由程序员来决定 线程如何响应中断, 但这对于线程来说是很常见的 终止。< / p >

它是如何实现的?

实现中断机制 使用内部标志 中断状态。调用 interrupt设置这个标志。当 线程通过检查中断 调用静态方法 中断状态 清除。非静态的 线程。被使用的isInterrupted 一个线程来查询中断 另一种状态,并不会改变

.中断状态标志

引用自Thread.interrupt() API:

中断该线程。首先, 该线程的checkAccess方法为 调用,这可能导致

. SecurityException抛出

如果线程阻塞在 调用wait(), wait(long), 方法的wait(long, int)方法 对象类,或者join()的 Join (long) Join (long, int) Sleep (long),或者Sleep (long, int) 方法的这个类,那么它 中断状态将被清除 它将接收一个 InterruptedException。< / p >

如果该线程在I/O阻塞 对可中断对象的操作 信道那么信道就是 关闭,线程的中断状态 将被设置,线程将

. receive一个ClosedByInterruptException.

. receive

如果这个线程在a中被阻塞 选择器,然后线程中断 Status会被设置,它会返回 从选择开始 操作,可能是非零的 值,就像选择器的 唤醒方法被调用

如果以上条件均不符合 保持该线程的中断

看看下面的内容,你就能完全理解:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

为了完整起见,除了其他答案,如果线程在__ABC0或Thread.sleep(..)等阻塞之前被中断,这相当于线程在阻塞该方法时立即被中断,如下例所示。

public class InterruptTest {
public static void main(String[] args) {


Thread.currentThread().interrupt();


printInterrupted(1);


Object o = new Object();
try {
synchronized (o) {
printInterrupted(2);
System.out.printf("A Time %d\n", System.currentTimeMillis());
o.wait(100);
System.out.printf("B Time %d\n", System.currentTimeMillis());
}
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("C Time %d\n", System.currentTimeMillis());


printInterrupted(3);


Thread.currentThread().interrupt();


printInterrupted(4);


try {
System.out.printf("D Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("E Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("F Time %d\n", System.currentTimeMillis());


printInterrupted(5);


try {
System.out.printf("G Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("H Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("I Time %d\n", System.currentTimeMillis());


}
static void printInterrupted(int n) {
System.out.printf("(%d) Am I interrupted? %s\n", n,
Thread.currentThread().isInterrupted() ? "Yes" : "No");
}
}

输出:

$ javac InterruptTest.java


$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669

含义:如果你像下面这样循环,并且中断发生在控制已经离开Thread.sleep(..)并且正在循环的确切时刻,异常仍然会发生。因此,在线程被中断后可靠地抛出InterruptedException是完全安全的:

while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
break;
}
}

公共无效中断()

中断这个线程。

除非当前线程正在中断自身(这总是允许的),否则调用该线程的checkAccess方法,这可能导致抛出SecurityException。

如果这个线程在Object类的wait()、wait(long)或wait(long, int)方法的调用中被阻塞,或者该类的join()、join(long)、join(long, int)、sleep(long)或sleep(long, int)方法的调用中被阻塞,那么它的中断状态将被清除,它将接收一个InterruptedException。

如果这个线程在一个可中断通道上的I/O操作中被阻塞,那么通道将被关闭,线程的中断状态将被设置,并且线程将收到一个ClosedByInterruptException。

如果这个线程在选择器中被阻塞,那么线程的中断状态将被设置,并且它将立即从选择操作中返回,可能是一个非零值,就像调用选择器的唤醒方法一样。

如果以上条件都不满足,则该线程的中断状态将被设置。

中断一个不活跃的线程不会有任何影响。

< p >扔:

. SecurityException -如果当前线程不能修改该线程
中断是对线程的一个指示,它应该停止正在做的事情并做其他事情。由程序员决定线程如何响应中断,但是线程终止是很常见的。 一个很好的参考:https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Thread.interrupt()将目标线程的中断状态/标志设置为true,当使用Thread.interrupted()检查时,可以帮助停止无休止的线程。参考http://www.yegor256.com/2015/10/20/interrupted-exception.html

线程中断基于标志中断状态。 对于每个线程,中断状态的默认值被设置为。 当线程上调用中断()方法时,中断状态被设置为真正的
  1. 如果中断状态= true(中断()已经在线程上调用), 特定线程不能进入睡眠状态。如果在该线程上调用sleep,则抛出中断异常。再次抛出异常后,标志被设置为false
  2. 如果线程已经处于睡眠状态,并且调用了中断(),线程将跳出睡眠状态并抛出中断的异常。

Thread.interrupt()方法设置内部的“中断状态”标志。通常该标志由Thread.interrupted()方法检查。

按照惯例,任何通过InterruptedException存在的方法都必须清除中断状态标志。

在以上回答的基础上,我想补充一两件事。

  1. 需要记住的一件事是,调用中断方法并不总是会导致InterruptedException。因此,实现代码应该定期检查中断状态并采取适当的操作。

  2. Thread.currentThread().isInterrupted()也可以用来检查线程的中断状态。与Thread.interrupted()方法不同,它不清除中断状态。