如何用interrupt停止线程

启动线程需要调用 thread 类的 start() 方法,并在 run() 方法中定义需要执行的任务。启动一个线程非常简单,但如果想要正确停止它就没那么容易了。
为什么不强制停止 对于 java 而言,最正确的停止线程的方式是使用 interrupt。但 interrupt仅仅起到通知被停止线程的作用。而对于被停止的线程而言,它拥有完全的自主权,它既可以选择立即停止,也可以选择一段时间后停止,也可以选择压根不停止。
为什么 java 不提供强制停止线程的能力呢?
事实上,java 希望程序间能够相互通知、相互协作地管理线程,因为如果不了解对方正在做的工作,贸然强制停止线程就可能会造成一些安全的问题。
比如:
线程正在写入一个文件,这时收到终止信号,它就需要根据自身业务判断,是选择立即停止,还是将整个文件写入成功后停止。如果选择立即停止就可能造成数据不完整,不管是中断命令发起者,还是接收者都不希望数据出现问题。
如何用 interrupt 停止线程 while (!thread.currentthread().isinterrupted() && more work to do) {    do more work} 我们一旦调用某个线程的 interrupt() 之后,这个线程的中断标记位就会被设置成 true。每个线程都有这样的标记位,当线程执行时,应该定期检查这个标记位,如果标记位被设置成 true,就说明有程序想终止该线程。
回到源码,可以看到在 while 循环体判断语句中,首先通过 thread.currentthread().isinterrupt() 判断线程是否被中断,随后检查是否还有工作要做。&& 逻辑表示只有当两个判断条件同时满足的情况下,才会去执行下面的工作。
来段代码瞅瞅。
public class stopthread implements runnable {     @override    public void run() {        int count = 0;        while (!thread.currentthread().isinterrupted() && count  {            int num = 0;            try {                while (!thread.currentthread().isinterrupted() && num <= 1000) {                    system.out.println(num);                    num++;                    thread.sleep(1000000);                }            } catch (interruptedexception e) {                e.printstacktrace();            }        };        thread thread = new thread(runnable);        thread.start();        thread.sleep(5);        thread.interrupt();    }} 运行后的结果你猜这么着,程序会抛出异常
如果 sleep、wait 等可以让线程进入阻塞的方法使线程休眠了,而处于休眠中的线程被中断,那么线程是可以感受到中断信号的,并且会抛出一个 interruptedexception 异常,同时清除中断信号,将中断标记位设置成 false。这样一来就不用担心长时间休眠中线程感受不到中断了,因为即便线程还在休眠,仍然能够响应中断通知,并抛出异常。
但是这样只能相应一次中断信号了,怎么办?
合理利用好 try/catch 我们在实际开发中不能盲目吞掉中断,如果不在方法签名中声明,也不在 catch 语句块中再次恢复中断,而是在 catch 中不作处理,我们称这种行为是“屏蔽了中断请求”。如果我们盲目地屏蔽了中断请求,会导致中断信号被完全忽略,最终导致线程无法正确停止。
    try {        thread.sleep(2000);    } catch (interruptedexception e) {//        此处处理中断异常请求    } 停止线程的方式有几种 void shutdown; boolean isshutdown; boolean isterminated; boolean awaittermination(long timeout, timeunit unit) throws interruptedexception; list shutdownnow; 下面我们就对这些方法逐一展开。
shutdown() 调用 shutdown() 方法之后线程池并不是立刻就被关闭,因为这时线程池中可能还有很多任务正在被执行,或是任务队列中有大量正在等待被执行的任务,调用 shutdown() 方法后线程池会在执行完正在执行的任务和队列中等待的任务后才彻底关闭。
但这并不代表 shutdown() 操作是没有任何效果的,调用 shutdown() 方法后如果还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。
isshutdown() 它可以返回 true 或者 false 来判断线程池是否已经开始了关闭工作,也就是是否执行了 shutdown 或者 shutdownnow 方法。这里需要注意,如果调用 isshutdown() 方法的返回的结果为 true 并不代表线程池此时已经彻底关闭了,这仅仅代表线程池开始了关闭的流程,也就是说,此时可能线程池中依然有线程在执行任务,队列里也可能有等待被执行的任务。
isterminated() 这个方法可以检测线程池是否真正“终结”了,这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了,因为我们刚才说过,调用 shutdown 方法之后,线程池会继续执行里面未完成的任务,不仅包括线程正在执行的任务,还包括正在任务队列中等待的任务。
比如此时已经调用了 shutdown 方法,但是有一个线程依然在执行任务,那么此时调用 isshutdown 方法返回的是 true ,而调用 isterminated 方法返回的便是 false ,因为线程池中还有任务正在在被执行,线程池并没有真正“终结”。直到所有任务都执行完毕了,调用 isterminated() 方法才会返回 true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。
awaittermination() 第四个方法叫作 awaittermination(),它本身并不是用来关闭线程池的,而是主要用来判断线程池状态的。比如我们给 awaittermination 方法传入的参数是 10 秒,那么它就会陷入 10 秒钟的等待,直到发生以下三种情况之一:
等待期间(包括进入等待状态之前)线程池已关闭并目所有已提交的任务(包括正在执行的和队列中等待的都执行完毕,相当于线程池已经“终结”了,方法便会返回true 等待超时时间到后,第一种线程池“终结”的情况始终未发生,方法返回 false 等待期间线程被中断,方法会抛出 interruptedexception异常 等待期间(包括进入等待状态之前)线程池已关闭并且所有已提交的任务(包括正在执行的和队列中等待的)都执行完毕,相当于线程池已经“终结”了,方法便会返回 true;
等待超时时间到后,第一种线程池“终结”的情况始终未发生,方法返回 false;等待期间线程被中断,方法会抛出 interruptedexception 异常。
shutdownnow() 最后一个方法是 shutdownnow(),也是 5 种方法里功能最强大的,它与第一种 shutdown 方法不同之处在于名字中多了一个单词 now,也就是表示立刻关闭的意思。参考这里:shutdown 和 shutdownnow 的区别
在执行 shutdownnow 方法之后,首先会给所有线程池中的线程发送 interrupt 中断信号,尝试中断这些任务的执行,然后会将任务队列中正在等待的所有任务转移到一个 list 中并返回,我们可以根据返回的任务 list 来进行一些补救的操作,例如记录在案并在后期重试。
public list shutdownnow() {     list tasks;    final reentrantlock mainlock = this.mainlock;    mainlock.lock();     try {         checkshutdownaccess();        advancerunstate(stop);        interruptworkers();        tasks = drainqueue();    } finally {         mainlock.unlock();    }      tryterminate();    return tasks; } 源码中有一行 interruptworkers() 代码,这行代码会让每一个已经启动的线程都中断,这样线程就可以在执行任务期间检测到中断信号并进行相应的处理,提前结束任务。
这里需要注意的是,由于 java 中不推荐强行停止线程的机制的限制,即便我们调用了 shutdownnow 方法,如果被中断的线程对于中断信号不理不睬,那么依然有可能导致任务不会停止。
总结 中断和关闭线程的方式五花八门,看起来很相似,其实里头大有门道。处理不好,可是会导致程序崩溃的。


中国工业计算机市场发展前景广阔,去年市场规模达到94亿元
流弊,华为2016年成就总结
近距离了解电动汽车中的直流滤波电容
LTE-M物联网连接套件和模块解决方案
移动办公的崛起,推进企业办公模式的进化发展
如何用interrupt停止线程
基于AMD器件的EtherCAT从站方案
音圈马达助力的苹果iPhone 15 Pro Max
计算机语言概述
有容乃大,化繁为简——夜神发布全新一代安卓模拟器
三星S8和苹果iPhone8在这部神机面前:不堪一击!
新品重磅发布,小米进军国际市场野心
海信E52A电视:双AI系统,家庭智能电视的首选
灵动微新推电机驱动及控制专用的MM32SPIN2x系列
LinkSwitch-TN2现已通过汽车级标准认证
AI能否成功引领智能家居中的智慧生活?
本源量子计算全栈式解决方案亮相2022全国“双创”活动周
分析智能马桶盖的电子组件和电路图
引领AI未来 | 软通动力携手华为云联合成立泰国AI云智社区
基于软件的优化手势识别解决方案