#每篇一句
不高看有钱人一眼,因为他的钱不给我花;不小瞧穷人一下,因为他不靠我生存;不巴结有权人,因为他不会白帮我办事;不奉承得志的小人,因为他不入我眼!我只知道感谢那些帮助我的人! 即使是帮我倒杯水~
中断线程的概念
中断是一种协作机制。当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情。相反,中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。
为什么废弃Thread的stop函数?
首先是stop的原理:
- stop是通过立即抛出ThreadDeath异常,来达到停止线程的目的,此异常抛出有可能发生在任何一时间点,包括在catch、finally等语句块中
- 由于有异常抛出,导致线程会释放全部所持有的锁,极可能引起线程安全问题
弊端说明:
synchronized {
x = 3;
y = 4;
}
本来代码块是synchronized标记的,保证x和y总是同时能被赋值,但假如A线程执行到x=3代码的时候,突然调用了stop方法,A线程立刻被杀死,导致出现了一个潜在的不安全的数据。这个就是stop的问题所在。它会强行把原子级的操作拆分,这是非常不安全的!
interrupt中断线程
interrupt() 它基于「一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。」思想,是一个比较温柔的做法,它更类似一个标志位。其实作用不是中断线程,而是「通知线程应该中断了」,具体到底中断还是继续运行,应该由被通知的线程自己处理。
interrupt() 并不能真正的中断线程,这点要谨记。需要被调用的线程自己进行配合才行。也就是说,一个线程如果有被中断的需求,那么就需要这样做:
- 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。
- 在调用阻塞方法时正确处理InterruptedException异常
中断正在运行中的线程
public class InterruptThread {
static class NoBlockThread {
Thread t = new Thread() {
public void run() {
while(true) {
if(!this.isInterrupted()) {
System.out.println("执行"+this.isInterrupted());
} else {
System.out.println("中断");
break;
}
}
};
};
}
public static void main(String[] args) throws InterruptedException {
NoBlockThread blockThread = new NoBlockThread();
blockThread.t.start();
Thread.sleep(4000);
System.out.println("睡眠结束");
blockThread.t.interrupt();
}
}
输入如下
…省略很多…
执行false
执行false
执行false
执行false
睡眠结束
执行false
执行false
执行false
中断true
可以看到,对于正常运行状态的线程, 可以通过判断线程中断状态标志
也就是isInterrupted()
方法来中断自己
中断阻塞中的线程
public class InterruptThread {
static class BlockThread {
Thread t = new Thread() {
public void run() {
while(!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(1000);
System.out.println("睡眠结束"+(Thread.currentThread() == this));
} catch (InterruptedException e) {
System.out.println("中断异常");
// 恢复中断状态
this.interrupt();// 再次中断线程
}
}
};
};
}
public static void main(String[] args) throws InterruptedException {
BlockThread blockThread = new BlockThread();
blockThread.t.start();
Thread.sleep(4000);
System.out.println("睡眠结束");
blockThread.t.interrupt();
}
}
运行结果:
睡眠结束false
睡眠结束false
睡眠结束false
睡眠结束
中断异常false
分析运行过程:
- main线程开启线程blockThread, 该线程有sleep()方法, 处于阻塞状态
- 4s后, main线程,发送一个通知blockThread.t.interrupt(); 把blockThread线程的
线程中断状态标志
设置成了true - 由于blockThread处于阻塞状态, 这时候,blockThread线程会立即被唤醒(停止阻塞),同时抛出InterruptedException异常,同时还会重置
线程中断状态标志
为false - 在捕获异常的时候,再此调用nterrupt();方法, 设置
线程中断状态标志
true, 这是就停止线程了
最重要的是: 如果线程处于sleep, wait, join 等状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常,同时重置线程中断状态标志
为false ;
我们想要中断线程,就必须捕获异常,并且在catch中对线程进行处理,否则无法中断线程
当一个方法抛出 InterruptedException 时,它不仅告诉您它可以抛出一个特定的检查异常,而且还告诉您其他一些事情。例如,它告诉您它是一个阻塞(blocking)方法,如果您响应得当的话,它将尝试消除阻塞并尽早返回。
注意:interrupt 操作不会打断所有阻塞,只有上述阻塞情况才在jvm的打断范围内,如处于锁阻塞的线程,不会受 interrupt 中断;