java非阻塞中断_Java线程中断

本文介绍了Java线程中断的概念,中断是线程间的一种协作机制,用于提示线程停止当前任务。中断并不会立即终止线程,而是由线程自行决定如何响应。文章通过中断位的设置与检查、中断的实现以及在非阻塞和阻塞方法中的中断处理进行了详细阐述,强调正确处理InterruptedException异常的重要性。
摘要由CSDN通过智能技术生成

Java线程中断

什么是线程中断

​中断是给线程的一个指示,告诉它应该停止正在做的事并去做其他事情(一般都是结束这个线程)。比如360正在执行杀毒扫描,我们点击“停止检测”就是一次线程中断。一个线程究竟要怎么响应中断请求取决于程序员,如果这个线程需要处理的任务很重要,那么线程可以忽略这个中断提醒。但一般相应中断的方法都是将该线程终止。

中断原理

​每个线程对象中都有一个boolean类型的状态位(不是Thread类中的字段,应该在C++源代码中),表示是否有中断请求(该请求可以来自所有线程,包括被中断的线程本身)。线程在执行某些方法时,总会不时的检测中断位,看看有没有中断请求,如果有就进行相应的处理。

​Java 中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程(仅仅是改变了中断位),而需要被中断的线程自己处理中断(可以忽略,也可以终止自己)。

中断位

获取中断位状态

主要有两种方法:

一种是Thread的静态方法interrupted,该方法会检测线程是否有中断请求,如果中断位为true,即目前该线程有中断请求,那么该方法会返回true并且将中断位重新设置位默认值false。

另一种是Thread对象的实例方法,isInterrupted。该方法也会检测线程是否有中断请求,这一点与interrupted方法相同。但不同的是,isInterrupted不会改变中断位的状态。

改变中断位状态

也是两种:

主要是通过Thread对象的实例方法:interrupt()。调用该方法后,线程的中断位会被设置为true,但并不是真正的中断了该线程。

也可以通过interrupted()方法将中断位设置为false。

中断的代码实现

主要可以分为两大类,一种是线程调用非阻塞方法时发生中断,另一种是调用阻塞方式时发生中断。当线程在执行方法时发生中断,那么就会抛出InterruptedException异常,并且将状态位设置位false。

阻塞方法

抛出InterruptedException的方法叫做阻塞方法.同样,不抛出InterruptedException的方法叫做非阻塞方法

执行非阻塞方法时发生中断

public class InterruptTest01 {

public static void main(String[] args) throws InterruptedException {

Thread interruptThread = new Thread(()->{

System.out.println("interruptThread线程正在运行。。。。。。");

while (true) {

if (Thread.currentThread().isInterrupted()){

System.out.println("检测到中断信号,终止线程");

// 或者其他处理

return;

}

}

}, "interruptThread");

interruptThread.start();

TimeUnit.SECONDS.sleep(5);

System.out.println(Thread.currentThread().getName() + "线程向" + interruptThread.getName() + "线程发出中断信号。。。。");

interruptThread.interrupt();

}

}

7f3298759c37025050dcb96255beacc6.png

执行阻塞方法时发生中断

package thread;

import java.sql.Time;

import java.util.concurrent.TimeUnit;

/**

* @author: OnlyOne

* @create: 2020-12-15 15:52

* @description:

**/

public class InterruptTest02 {

public static void main(String[] args) throws InterruptedException {

Thread interruptThread = new Thread(()->{

try {

while (true) {

System.out.println("interruptThread线程即将沉睡5秒。。。。。");

TimeUnit.SECONDS.sleep(5);

}

}catch (InterruptedException e) {

System.out.println("捕获到InterruptedException异常。。。。");

System.out.println("此时中断位:" + Thread.currentThread().isInterrupted());

return;

}

}, "interruptThread");

interruptThread.start();

// main线程沉睡两秒,好让interruptThread线程沉睡

TimeUnit.SECONDS.sleep(2);

System.out.println(Thread.currentThread().getName() + "线程向" + interruptThread.getName() + "线程发出中断信号。。。。");

interruptThread.interrupt();

}

}

df0099ef87451dc1d5413272e30a9f2e.png

以上程序中,当main线程向interruptThread线程发出中断请求后,interruptThread的状态位被设置为true。但此时interruptThread线程正在调用阻塞方法,因此就会抛出InterruptedException异常。

如何处理InterruptedException

当线程在执行时需要处理InterruptedException异常时,不要简单的将其忽略,因为抛出InterruptedException异常后该线程的中断位就会被擦除(如果没有对此中断进行处理),设置为默认的false,这样就会造成中断请求的丢失。比如使用try catch捕获异常,但在catch中不对中断进行处理。

这种情况下就有两种比较可取的方式:

第一种,在catch块中调用interrupt(),从新将中断位置为true,这样以后还可以检测出该中断

第二种,不要catch这个异常,使用throws声明,让方法的调用者去处理。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值