目录
最难的
面试题
什么是中断 理论
首先
一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。
所以,Thread.stop,Thread.suspend, Thread.resume 都已经被废弃了。
其次
在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。
因此,Java提供了一种用于停止线程的机制--中断。
中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。
若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true;
接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断,
此时究竟该做什么需要你自己写代码实现。
每个线程对象中都有一个标识,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断:
通过调用线程对象的interrupt方法将该线程的标识位设为true;可以在别的线程中调用,也可以在自己的线程中调用。
多线程中
每一条线程的命运掌握在自己手中
中断
中断协商机制
调用方法 interrupt 发起中断协商机制
注意只是协商
并不是 立即 + 马上 + now, stop 一个线程
不允许停别人的线程
但不是立刻停止这个线程
只是发起中断协商机制
接着你需要写代码不断记得检测当前线程的标识位
如果为 true
标识别的线程要求这条线程中断
每个线程对象中都有一个表示用于表示当前线程是否被中断
标识位为 true 为中断 false 未中断
通过调用线程对象的 interrupt 方法将该线程的表示为设为 true 可以在别的线程里面调用 也可以在自己的线程里面调用
中断 API 的相关方法
如何使用中断标志位中断线程
在需要中断的线程中不断监听中断状态
一旦发生中断
就执行相应的中断处理业务逻辑
通过一个 volatile 变量实现
volatile变量具有可见性
在一个线程里面修改 volatile 变量
另一个线程是完全可见的
import java.util.concurrent.TimeUnit;
public class InterruptDemo {
// 如何在多线程环境下优雅的退出某个线程
static volatile boolean isStop = false;
public static void main(String[] args) {
// 通过一个volatile变量实现
new Thread(() ->{
while (true){
if(isStop){
System.out.println("程序结束");
break;
}
System.out.println("hello isStop");
}
},"t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// volatile变量具有可见性
new Thread(() ->{
isStop = true;
},"t2").start();
}
}
通过原子操作类实现
原子操作类
AtomicBoolean
public static void main(String[] args) {
new Thread(() ->{
while (true){
if(atomicBoolean.get()){
System.out.println("程序结束");
break;
}
System.out.println("hello isStop");
}
},"t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
atomicBoolean.set(true);
},"t2").start();
}
用 Thread 自带的中断 API 方法
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class InterruptDemo {
// 如何在多线程环境下优雅的退出某个线程
// volatile修饰的变量
static volatile boolean isStop = false;
// 原子操作类 AtomicBoolean
static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("程序结束");
break;
}
System.out.println("hello isStop");
}
}, "t1");
t1.start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
// 修改t1线程的中断标志位为true
t1.interrupt();
},"t2").start();
}
public static void m1(String[] args) {
// 通过一个volatile变量实现
new Thread(() ->{
while (true){
if(isStop){
System.out.println("程序结束");
break;
}
System.out.println("hello isStop");
}
},"t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// volatile变量具有可见性
new Thread(() ->{
isStop = true;
},"t2").start();
}
public static void m2(String[] args) {
// 通过原子操作类实现
new Thread(() ->{
while (true){
if(atomicBoolean.get()){
System.out.println("程序结束");
break;
}
System.out.println("hello isStop");
}
},"t1").start();
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
atomicBoolean.set(true);
},"t2").start();
}
}
源码解析 interrupt()
源码解析 isInterrupt()
样例 1 简单 正常打断
import java.util.concurrent.TimeUnit;
public class InterruptHardDemo {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("t1 线程别打断了程序结束");
break;
}
// System.out.println("hello isStop");
}
}, "t1");
t1.start();
System.out.println(t1.isInterrupted());
// 暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// new Thread(() ->{
// // 修改t1线程的中断标志位为true
// t1.interrupt();
// },"t2").start();
t1.interrupt();
System.out.println(t1.isInterrupted());
}
}
中断不是立即 stop
样例 2 困难 不会立刻打断
输出
非活动线程的中断标志为 false
样例 3 困难 强制打断 重要
3 秒后正常打断
输出
强制打断
这种是停止不了的
很容易造成生产事故
跟底层原理有关
在异常里面处理
输出
其实就是线程中断标志位复位为 false
无法停下
需要再次调方法
将中断标志位设置为 true
静态方法 interrupt()
结论
代码
输出
因为存在一个状态清空的逻辑