这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
线程中断interrupt
- interrupt() 的作用是中断当前线程
- 当前线程可以中断本身运行的线程,如果其余线程调用本线程的interrupt() 方法时,会通过checkAccess() 检查权限,会抛出SecurityException异常
- 如果本线程因为调用线程的wait() 方法 ,wait(long) 或者wait(long, int), 或者是调用了线程的join(), join(long),join(long, int),sleep(long),sleep(long, int) 进入阻塞状态时,调用interrupt() 方法,那么该线程的 [中断状态] 就会被清除并且会收到一个InterruptedException异常
- 如果线程阻塞在一个Selector选择器中,那么通过interrupt() 中断时,线程的中断标记会被设置为true, 并且会立即从选择操作中返回
- 通过interrupt() 中断线程时,中断标记会被设置为true, 中断一个 [已经终止的线程] 不会产生任何操作
终止线程
阻塞状态
- 一般情况下,通过中断interrupt方式终止处于 [阻塞状态] 的线程
- 当前线程通过调用sleep(),wait(),join() 等方法进入阻塞状态,若此时调用线程的interrupt() 方法可以将线程的中断标记设置为true
- 由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常
- 将InterruptedException异常放在适当的位置就能终止线程
@Override
public void run() {
try {
while (true) {
// 运行线程
}
} catch (InterruptedException e) {
// 捕获到产生的InterruptedException异常,退出while(true)循环,线程终止
}
}
复制代码
- 在while(true) 中不断执行任务,当线程处于阻塞状态时,调用线程的interrupt() 产生InterruptedException异常,中断的异常在while(true) 之外捕获,这样就可以退出while循环,终止异常
- 对InterruptedException的捕获一般放在while(true) 循环体外,这样就可以在产生异常时退出while(true) 循环.如果对InterruptedException的捕获放置在while(true) 循环体之内,就需要添加额外的退出处理
运行状态
- 一般情况下,通过 [标记] 终止处于 [运行状态] 的线程
- 标记包括: 中断标记和额外添加标记
中断标记
@Override
public void run() {
while (!isInterrupted) {
// 运行线程
}
}
复制代码
- isInterrupted() 方法用于判断线程的中断标记是否为true:
- 当线程处于运行状态,并且需要终止时,可以调用线程的interrupt() 方法,将线程的中断标记设置为true. 此时isInterrupted() 会返回true, 此时就会退出while循环
- interrupt() 并不会终止处于 [运行状态] 的线程,只是将线程的中断标记设置为true
额外添加标记
private volatile boolean flag = true;
protected void stopTask() {
flag = false;
}
@Override
public void run() {
while (flag) {
// 运行任务
}
}
复制代码
- 线程中有一个flag标记,默认值为true
- 可以通过stopTask() 方法来设置flag标记,当需要终止该方法时,调用该线程的stopTask() 方法就可以让线程退出循环
- 使用volatile定义flag类型: 保证flag的可见性.即其余线程通过调用stopTask() 方法修改了flag的值之后,本线程可以看到修改后flag的值
综合状态线程
- 综合状态线程: 处于阻塞状态和运行状态的线程
- 综合状态线程的通用终止方式:
@Override
public void run() {
try {
// isInterrupted保证只要中断标记为true就终止线程
while (!isInterrupted()) {
// 运行线程
}
} catch (InterruptedException e) {
// InterruptedException保证只要当InterruptedException异常产生时就终止线程
}
}
复制代码
interrupted()和isInterrupted()异同
- 相同点: interrupted() 和isInterrupted() 都能够用于检测对象的 [中断标记]
- 不同点:
- interrupted() 除了返回 [中断标记] 之外,还会清除 [中断标记], 即将 [中断标记] 设置为false
- isInterrupted() 仅仅返回 [中断标记]