java多线程之——停止线程多种方式

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());
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是X大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值