线程协作-中断
一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果. 所以你看到线程的suspend()、resume()和stop()方法(线程的暂停、恢复和终
止)被废弃
应用场景:
(1)不能直接把一个线程搞挂掉, 但有时候又有必要让一个线程死掉, 或者让它结束某种等待的状态该怎么办呢? 优雅的方法就是,
给那个线程一个中断信号, 让它自己决定该怎么办。
(2)在某个子线程中为了等待一些特定条件的到来, 你调用了Thread.sleep(10000), 预期线程睡10秒之后自己醒来, 但是如果这个特定条件提前到来的话, 你怎么通知一个在睡觉的线程呢?(主线程中断子线程)
(3) 主线程通过调用子线程的join方法阻塞自己以等待子线程结束, 但是子线程运行过程中发现自己没办法在短时间内结束, 于是它需要想办法告诉主线程别等我了。(子线程中断主线程)
中断实现:
中断是通过调用Thread.interrupt()方法来做的。这个方法通过修改了被调用线程的中断状态来告知那个线程,
说它被中断了。
对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true;
对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(),
Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为false。
程序演示:
下面的程序会演示对非阻塞中的线程中断:
public class Main {
public static class Thread3 extends Thread{
public void run(){
while(true){
if(Thread.interrupted()){//返回true, 但是中断状态置回为false
System.out.println("Someone interrupted me.");
} else{
System.out.println("Going...");
}
long now = System.currentTimeMillis();
while(System.currentTimeMillis()-now<1000){
// 为了避免Thread.sleep()而需要捕获InterruptedException而带来的理解上的困惑,
// 此处用这种方法空转1秒
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread3 t = new Thread3();
t.start();
Thread.sleep(3000);
t.interrupt();
System.out.println("hahah");
}
}
下面的程序演示的是子线程通知父线程(阻塞中)别等它了:
public class Main {
public static class Thread4 extends Thread {
private Thread parent;
public Thread4(Thread parent) {
this.parent = parent;
}
public void run() {
while (true) {
System.out.println("sub thread is running...");
long now = System.currentTimeMillis();
while (System.currentTimeMillis() - now < 2000) {
// 为了避免Thread.sleep()而需要捕获InterruptedException而带来的理解上的困惑,
// 此处用这种方法空转2秒
}
parent.interrupt();
}
}
}
public static void main(String[] args){
Thread4 t = new Thread4(Thread.currentThread());
t.start();
try {
Thread.sleep(10000);
t.wait();
t.join();
} catch (InterruptedException e) {
System.out.println(Thread.interrupted());
System.out.println(Thread.currentThread().isInterrupted());
System.out.println("Parent thread will die...");
}
}
}
注意:
1. 中断状态可以通过 Thread.isInterrupted()来读取,并且可以通过一个名为 Thread.interrupted()的静态方法读取和清除状态(即调用该方法结束之后, 中断状态会变成false)。
2. 不是所有的阻塞方法收到中断后都可以取消阻塞状态: 输入和输出流类会阻塞等待 I/O 完成,收到中断后,它们不抛出 InterruptedException,而且在被中断的情况下也不会退出阻塞状态。
3.尝试获取一个内部锁的操作(进入一个 synchronized 块)是不能被中断的,但是 ReentrantLock 支持可中断的获取模式即 tryLock(long time, TimeUnit unit)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战