201.md 2.6 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4
# 中断

> 原文: [https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html](https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html)

W
wizardforcel 已提交
5
*中断*表示线程应该停止正在进行的操作并执行其他操作。由程序员决定线程如何响应中断,但线程终止是很常见的。这是本课程中强调的用法。
W
init  
wizardforcel 已提交
6 7 8 9 10 11 12

线程通过调用`Thread`对象上的 [`interrupt`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupt--) 来发送中断,以便中断线程。为使中断机制正常工作,被中断的线程必须支持自己的中断。

## 支持中断

线程如何支持自己的中断?这取决于它目前正在做什么。如果线程经常调用抛出`InterruptedException`的方法,它只会在捕获该异常后从`run`方法返回。例如,假设`SleepMessages`示例中的中央消息循环位于线程的`Runnable`对象的`run`方法中。然后可以按如下方式修改它以支持中断:

W
wizardforcel 已提交
13
```java
W
init  
wizardforcel 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
for (int i = 0; i < importantInfo.length; i++) {
    // Pause for 4 seconds
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // We've been interrupted: no more messages.
        return;
    }
    // Print a message
    System.out.println(importantInfo[i]);
}

```

抛出`InterruptedException`的许多方法(如`sleep`)旨在取消当前操作,并在收到中断时立即返回。

如果一个线程长时间没有调用抛出`InterruptedException`的方法怎么办?然后它必须定期调用`Thread.interrupted`,如果收到中断则返回`true`。例如:

W
wizardforcel 已提交
32
```java
W
init  
wizardforcel 已提交
33 34 35 36 37 38 39 40 41 42 43 44
for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        // We've been interrupted: no more crunching.
        return;
    }
}

```

在这个简单的例子中,代码只是测试中断并退出线程(如果已收到)。在更复杂的应用程序中,抛出`InterruptedException`可能更有意义:

W
wizardforcel 已提交
45
```java
W
init  
wizardforcel 已提交
46 47 48 49 50 51 52 53 54 55
if (Thread.interrupted()) {
    throw new InterruptedException();
}

```

这允许中断处理代码集中在`catch`子句中。

## 中断状态标志

W
wizardforcel 已提交
56
中断机制使用称为*中断状态*的内部标志来实现。调用`Thread.interrupt`设置此标志。当线程通过调用静态方法`Thread.interrupted`检查中断时,中断状态被清除。非静态`isInterrupted`方法(由一个线程用于查询另一个线程的中断状态)不会更改中断状态标志。
W
init  
wizardforcel 已提交
57 58

按照惯例,任何通过抛出`InterruptedException`退出的方法都会清除中断状态。但是,通过调用`interrupt`的另一个线程,总是可以立即再次设置中断状态。