hello,大家好这里是X,这里带来我总结的几种线程中断的方式,算是一个小合集~🚩
关于Java的中断我很早之前写过一篇博客,讲了停止线程的interrupted和isInterrupted的区别和各自的用法总结,传送门,可以先去看看这篇博文
中断系统一般包含:中断源、中断信号[一个信号标识]、中断控制器、中断处理器💁♀️
ppp:今天是水果专题🍒🍐🍓
Java的中断机制使用一个中断变量作为标识,假如某个线程的中断变量被标记为true,那么这个线程在适当的时机会抛出异常,程序员捕获异常后进行相应的处理。要玩转线程中断,首先必须明白中断标识是如何检测和触发的。🐵
中断标识方式🍊
针对“正在运行”的线程😎
java层自定义
package com.thread.threadSafe.stop;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-20 19:15
* 在Java层自定义中断标识
**/
public class InterruptThreadDemo extends Thread{
private volatile boolean isInterrupted = false;
public void customInterrupt(){
isInterrupted = true;
}
@Override
public void run() {
while (!isInterrupted){
System.out.println("我在跑!!");
}
System.out.println("我被打断啦!!");
}
public static void main(String[] args) {
InterruptThreadDemo threadDemo = new InterruptThreadDemo();
threadDemo.start();
try {
Thread.sleep(100);
}catch (InterruptedException e){
}
threadDemo.customInterrupt();
}
}
使用JVM提供的中断标识
package com.thread.threadSafe.stop;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-20 19:15
* 在Java层自定义中断标识
**/
public class InterruptThreadDemo2 extends Thread{
@Override
public void run() {
while (!Thread.interrupted()){
System.out.println("我在跑!!");
}
System.out.println("我被打断啦!!");
}
public static void main(String[] args) {
InterruptThreadDemo2 threadDemo = new InterruptThreadDemo2();
threadDemo.start();
try {
Thread.sleep(100);
}catch (InterruptedException e){
}
threadDemo.interrupt();
}
}
结果和上面一样
阻塞/等待状态中断方式🍉
对于可以运行的线程,我们需要通过while的形式来检测中断标识,而对于本身已经处于阻塞/等待状态的线程,则无需自己检测中断标识,我们要做的就是捕获中断异常并进行处理。😎
这里需要注意的就是:sleep会清除中断状态
睡眠
package com.thread.threadSafe.sleep.stop;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-19 22:08
**/
public class MyThread extends Thread{
@Override
public void run() {
super.run();
try {
System.out.println("run begin");
Thread.sleep(2000);
System.out.println("run end");
}catch (InterruptedException e){
System.out.println("在沉睡中被停止!进入了catch!!!!"+this.isInterrupted());
e.printStackTrace();
}
}
/**
* run begin
* main end!!
* 在沉睡中被停止!进入了catch!!!!false
* java.lang.InterruptedException: sleep interrupted
* at java.base/java.lang.Thread.sleep(Native Method)
* at com.thread.threadSafe.sleep.stop.MyThread.run(MyThread.java:15)
* 如果线程在sleep方法中被打断,那么线程会进入catch语句,并且清除停止状态,变成false
* 注意:这里是先sleep(),再interrupt()
* 最终的结论:不管这两个方法谁先执行,只要是他们两个方法碰一起了,就必定会出现异常
*/
}
Run方法
package com.thread.threadSafe.sleep.stop;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-19 22:09
**/
public class Run {
public static void main(String[] args) throws InterruptedException {
try {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(200);
myThread.interrupt();
}catch (InterruptedException e){
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("main end!!");
}
}
运行结果
其他的经典情景🍍
如果线程既可能处于可执行状态、又可能处于阻塞/中断状态,怎么处理?
这里其实就是对上面两个方法进行一个“综合”🥪
🥝既要有通过while循环来判断是否中断,在这个while循环中,线程还可能进入睡眠状态,睡眠状态是由JVM层面去支持中断的,所以当这个线程调用了中断方法之后,它会中断睡眠并抛出中断异常
🥑还记得上面说过的一个注意点吗,sleep捕获了异常之后它会清除中断标识,然后抛出异常,因为这个中断标识会被清除掉,所以我们要再次设置一下中断标识,不然上面的while循环跳不出来啦
package com.thread.threadSafe.stop;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-21 10:02
**/
public class RunningWatingInterrupt {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()){
System.out.println("running...");
try {
Thread.sleep(200);
}catch (InterruptedException e){
System.out.println(Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
System.out.println("thread has stoped!");
}
}
});
thread.start();
try {
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
thread.interrupt();
}
}
park的特殊中断
实际上通过park方式阻塞线程,它的终端方法比较特殊,这种阻塞方式下的中断不会抛出中断异常,但是中断标识会被设置成true,不会清除这个中断标识。
package com.thread.threadSafe.stop;
import java.util.concurrent.locks.LockSupport;
/**
* @program: thread
* @author: xmonster_大魔王
* @create: 2022-09-21 10:30
**/
public class park {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("i am running!!");
LockSupport.park(); //关键点
});
thread.start();
try {
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
thread.interrupt();
System.out.println(thread.isInterrupted());
}
}