Java:关于Java中的线程中断的几种方法
1.使用线程的stop()来中断线程
2.使用线程的interrupt()来中断线程
3.通过共享变量来控制
使用线程的stop()来中断线程
这种方式是直接调用线程的stop()方法,可以直接让线程终止运行,是一种很暴力的方式。
public static void test02(){
Thread thread1 = new Thread(()->{
System.out.println("thread1启动了");
while (true){
System.out.println("thread1循环中...");
}
});
thread1.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("准备关闭thread1线程");
thread1.stop();
System.out.println("主线程停止");
}
运行结果如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/74bef0756dd5471aaa254c476356e453.jpeg#pic_center)
使用线程的interrupt()来中断线程
public static void testInterrupt(){
Thread thread1 = new Thread(() -> {
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
System.out.println("thread1线程被中断");
break;
}
System.out.println("thread1循环中...");
}
});
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
运行结果如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/3d0822dbcbd847479b8e131f524529a7.jpeg#pic_center)
interrupt相比于stop中断线程的方式更加温柔,当主线程调用thread1线程的interrupt方法其实本质就是将thread1线程的中断标志设置为true,仅此而已。被设置中断标志的线程还是可以继续运行的,不受影响,也就是如果thread不主动结束线程该线程是不会停止的。
代码演示如下
public static void testInterrupt2(){
Thread thread1 = new Thread(() -> {
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
System.out.println("当前中断标志位状态为:"+interrupted);
System.out.println("thread1循环中...");
}
});
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
运行结果如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/8038274e77e340938969537b99841379.jpeg#pic_center)
当调用了thread1.interrupt();之后thread1还会一直无限执行下去。
如果thread1线程处于被阻塞状态(例如处于sleep,wait,join等状态),在别的线程调用thread1的interrupt方法,那么线程的中断状态会被清除,并抛出InterruptedException异常
代码如下
public static void testInterrupt3(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1线程启动了。。。");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
运行结果如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/863400b799f742d380648fa6631a1f2f.jpeg#pic_center)
1.线程启动是,默认中断标志位为false
2.如果main线程调用了thread1的interrupt()方法,中断标志位就变成了true
3.正常情况,中断标志位为true,如果thread1判断中断标志位为true就中断执行,则thread1停止,如果thread1线程自己不终止运行则不会停止。
4.异常情况,如果thread1线程正处于阻塞状态(例如处于sleep,wait,join等状态),将会把中断状态清除,并且将抛出InterruptedException异常,此时中断标志位还是false,thread1线程还会继续执行。
测试异常情况,并且循环不停止的情况,代码如下
public static void testInterrupt4(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1线程启动了。。。");
try {
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
System.out.println("thread1程序终止");
break;
}
}
});
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/9b64fb8ef2f7484dbbddf9b65da0ae58.jpeg#pic_center)
程序并没有停止
5.解决异常情况的方法,就是在catch块中,需要再次将中断标志位设置为true,2次调用才能使中断标志位改为true
public static void testInterrupt5(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1线程启动了。。。");
try {
Thread.sleep(5000);
} catch (Exception e) {
// 抛出异常过后在此调用interrupt方法
Thread.currentThread().interrupt();
e.printStackTrace();
}
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
System.out.println("thread1程序终止");
break;
}
}
});
thread1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/4072763c331b40e2985062bc8e619c64.jpeg#pic_center)
关于Thread.interrupted()方法
判断线程是否被中断并清除当前中断状态
这个方法做了两件事情
1.返回当前线程的中断状态
2.将当前线程的中断状态清零并重新设置为false,清除线程的中断状态
public static void testInterrupt6(){
System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
System.out.println("1111111111111111");
// 中断标志位设置为true
Thread.currentThread().interrupt();
System.out.println("2222222222222222");
System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted());
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/772d0afaa8cc4025bb3b75a8819d7487.jpeg#pic_center)
关于isInterrupted()方法
该方法只会返回当前线程的中断标志位的状态;不会清除当前线程的中断标志位的状态
public static void testInterrupt7(){
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
System.out.println("1111111111111111");
// 中断标志位设置为true
Thread.currentThread().interrupt();
System.out.println("2222222222222222");
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted());
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/d2ee78aa732244c3a269bd2919f7ea54.jpeg#pic_center)
关于Thread的静态方法interrupted和Thread实例方法isInterrupted底层源码
1.interrupted
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
2.isInterrupted
public boolean isInterrupted() {
return isInterrupted(false);
}
本质上都是调用了实例的isInterrupted方法,只是传入的参数有所不同,当传入true时,会情空当前线程的中断标志,重置为false,方传入false时,不会清空。
private native boolean isInterrupted(boolean ClearInterrupted);
该方法是被native修饰的方法
总结
- public void interrupt() 其中interrupt()是一个实例方法
它通知目标线程中断,也仅仅是设置目标线程的中断标志位为true.
- public boolean isInterrupted() 其中isInterrupted()方法也是一个实例方法
它判断当前线程是否被中断(通过检查中断标志位)并获得中断标志
- public static boolean interrupted() . 该方法是Thread类的静态方法
返回当前线程的中断状态真实值后会将当前线程的中断状态设置为false,此方法调用之后会清除当前线程的中断标志位的状态。
通过共享变量来控制
1.使用volatile 关键字来实现线程中断
static volatile boolean run = true;
public static void main(String[] args) {
new Thread(()->{
while (run){
System.out.println("线程1执行中...");
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run = false;
System.out.println("主线程结束");
}
2.使用同步代码块synchronized来实现线程中断
static boolean run = true;
static Object object = new Object();
public static void main(String[] args) {
new Thread(()->{
while (run){
System.out.println("线程1执行中...");
synchronized (object){
}
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run = false;
System.out.println("主线程结束");
}
3.使用AtomicBoolean 来实现线程中断
public static void main(String[] args) {
AtomicBoolean run = new AtomicBoolean(true);
new Thread(()->{
while (run.get()){
System.out.println("线程1执行中...");
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run.set(false);
System.out.println("主线程结束");
}
其运行结果如下![在这里插入图片描述](https://img-blog.csdnimg.cn/7edfb96c9f404109a66b6fedbf017257.jpeg#pic_center)