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

one*_*eat 199 java multithreading

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

Mik*_*e Q 242

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

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

轮询通过Thread.interrupted()返回当前线程的中断状态的方法进行,并清除该中断标志.通常,线程可能会执行诸如抛出InterruptedException之类的操作.

编辑(来自Thilo评论):一些API方法内置了中断处理.这包括我的头脑.

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

编辑(来自@ thomas-pornin的回答完全相同的问题)

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

  • 请注意,像sleep或wait这样的方法会执行此类轮询并自行抛出InterruptedException. (19认同)
  • 如果您提到 Thread.interrupted,似乎应该提到还有一个 Thread.isInterrupted 标志,它不会清除该标志,这使得它通常更适合应用程序开发人员使用。 (2认同)

YoK*_*YoK 64

什么是中断?

中断是一个线程的指示,它应该停止正在做的事情并做其他事情.由程序员决定线程如何响应中断,但线程终止是很常见的.

它是如何实现的?

中断机制使用称为中断状态的内部标志来实现.调用Thread.interrupt设置此标志.当线程通过调用静态方法Thread.interrupted来检查中断时,将清除中断状态.非静态Thread.isInterrupted,这是使用一个线程来查询另一中断状态,不会改变中断状态标志.

来自Thread.interrupt()API的报价:

中断此线程.第一这个线程的checkAccess方法被调用,这可能导致一个SecurityException被抛出.

如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long,int)方法中阻塞了这个线程,sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException.

如果此线程在可中断通道上的I/O操作中被阻塞,则通道将被关闭,线程的中断状态将被设置,并且线程将收到ClosedByInterruptException.

如果此线程在Selector中被阻塞,则线程的中断状态将被设置,并且它将立即从选择操作返回,可能具有非零值,就像调用选择器的唤醒方法一样.

如果以前的条件都不成立,则将设置该线程的中断状态.

检查这一点是为了完全理解相同的:

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


Thi*_*ilo 11

如果目标线程一直在等待(通过调用wait(),或其他基本上做同样事情的其他相关方法,例如sleep()),它将被中断,这意味着它停止等待它等待的内容并改为接收InterruptedException.

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

它有时与终止标志结合使用.中断时,线程可以检查此标志,然后自行关闭.但同样,这只是一个惯例.


Evg*_*eev 10

为了完整性,除了其他答案之外,如果线程在阻塞之前被中断Object.wait(..)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");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ 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
Run Code Online (Sandbox Code Playgroud)

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

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

线程中断基于标志中断状态。对于每个线程,中断状态的默认值设置为false。每当在线程上调用interrupt()方法时,中断状态都会设置为true

  1. 如果中断状态 = true(interrupt() 已在线程上调用),则该特定线程无法进入睡眠状态。如果在该线程上调用 sleep 会引发中断异常。再次抛出异常后,标志设置为 false。
  2. 如果线程已经在休眠并且调用了interrupt(),则线程将退出休眠状态并抛出中断的异常。