Java中如何终止一个线程?

一、先看下Java中线程的状态

ff8b0db4e663f56ed3bd59b0661ca792.png

二、如何终止一个正在sleep、waiting、blocked状态的线程?

方法1:优雅方案,发中断信号,终止的决定权交给业务代码

/**
 * @Project fighting-core
 * @Description  如何终止一个正在sleep的线程?
 * @Author lvaolin
 * @Date 2021/5/25 5:26 下午
 */
public class Demo01 {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("愉快的开始");
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println("愉快的结束");
                } catch (InterruptedException e) {
                    System.out.println("我被终止了"+System.currentTimeMillis());
                    return;
                }
                 System.out.println("do something");
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
        System.out.println("over");
        System.in.read();
    }
}

方法2 使用stop方法终止线程(过于暴力,此方法已被标记为过时、放弃,不建议使用)

/**
 * @Project fighting-core
 * @Description  如何终止一个正在sleep的线程?
 * @Author lvaolin
 * @Date 2021/5/25 5:26 下午
 */
public class Demo02 {
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("愉快的开始");
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println("愉快的结束");
                } catch (InterruptedException e) {
                    System.out.println("我被终止了"+System.currentTimeMillis());
                    return;
                }
                System.out.println("do something");
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        thread.stop();
        System.out.println("over");
        System.in.read();
    }
}

三、如何终止一个死循环中的线程?

如果你希望你的业务线程有能力被中断,具有可中断性,请再循环条件里判断 Thread.currentThread().isInterrupted() 或者 Thread.interrupted() ,它们的区别见末尾的总结部分

/**
 * @Project fighting-core
 * @Description 如何终止一个死循环?
 * @Author lvaolin
 * @Date 2021/5/25 22:07 下午
 */
public class Demo07 {
    public static void main(String[] args) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true && !Thread.currentThread().isInterrupted()) {
                    System.out.println("愉快的开始");
                    System.out.println("愉快的结束");
                }
                System.out.println("我被终止了,运行了" + (System.currentTimeMillis()-startTime)+"ms");
            }
        });
        thread.start();
        TimeUnit.MILLISECONDS.sleep(1);
        System.out.println("发送中断信号----");
        thread.interrupt();
        System.in.read();
    }
}

三、如何终止一个正常执行指令的线程?

/**
 * @Project fighting-core
 * @Description 如何终止一个正常运行的程序?
 * @Author lvaolin
 * @Date 2021/5/25 22:07 下午
 */
public class Demo08 {
    public static void main(String[] args) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //while (true){
                    //模拟正常运行的业务代码----如果希望业务具备中断能力,就需要多埋点判断中断的状态标志--
                    if(Thread.interrupted()){
                        System.out.println("我被中断了1");
                        return;
                    }
                    System.out.println("do something1");
                    if(Thread.interrupted()){
                        System.out.println("我被中断了2");
                        return;
                    }
                    System.out.println("do something2");
                    if(Thread.interrupted()){
                        System.out.println("我被中断了3");
                        return;
                    }
                    System.out.println("do something3");
                }


            //}
        });
        thread.start();
        TimeUnit.MILLISECONDS.sleep(1);
        System.out.println("发送中断信号----");
        thread.interrupt();
        System.in.read();
    }
}

四、如何终止一个线程池中的正在执行的任务?

线程池中的任务只能使用中断信号去尝试中断已经开始的任务,无法使用stop方法暴力终止一个线程,因为没有暴露API能获取到线程引用

/**
 * @Project fighting-core
 * @Description 如何终止一个在线程池中运行的任务?
 * @Author lvaolin
 * @Date 2021/5/25 22:49 下午
 */
public class Demo10 {
    static ExecutorService service = Executors.newFixedThreadPool(5);
    public static void main(String[] args) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Future<?> future = service.submit(new Runnable() {
            @Override
            public void run() {
                while (true&&!Thread.interrupted()){//具有中断能力的任务
                //while (true){//不具有中断能力的任务,一旦开始就不能取消
                    System.out.println("do something");
                }
                System.out.println("任务被取消");
            }
        });
        TimeUnit.MILLISECONDS.sleep(1000);
        System.out.println("发送中断信号----");
        //取消任务,参数true决定了即使任务已经开始运行,也会向任务发中断信号,
        // 但是不能保证一定会被中断,和业务代码是否具有中断能力有关
        future.cancel(true);
        System.in.read();
    }
}

总结

方法有两种:

1、JDK早期只提供了 Thread.stop()方法,缺点很明显,暴力终止一个线程,程序员没有任何选择的机会;

2、后来提供了优雅的方法,给了程序员选择的能力:therad.interrupt() 会向目标线程发送中断信号,对于处于sleep、wait、blocked状态的目标线程会引发InterruptedException异常,至于异常后程序该何去何从,由程序员决定。对于正常运行的程序,如果不理会这个中断信号,则不会收到任何影响;如果想让业务代码具有中断能力,则需要埋点检测中断信号的状态。

3、Thread.interrupted() 与Thread.currentThread().isInterrupted()区别

Thread.interrupted() 会同时清除中断标志,如果连续执行2次这句代码,第1句结果为true,第2句代码得到的结果会是false

//这是它的源码
public static boolean interrupted() {
    return currentThread().isInterrupted(true);//参数true决定了会清除中断标志
}

Thread.currentThread().isInterrupted()不会清除中断标志,如果连续执行2次这句代码,第1句结果为true,第2句代码得到的结果也会是true

//这是它的源码
public boolean isInterrupted() {
    return isInterrupted(false);//参数false决定了不会清除中断标志
}

4、关于future.cancel(true);  当参数为false时,只能取消还没有开始的任务。当参数为true时,如果任务还没开始,那么就正常取消;如果任务已经开始,那么就向线程发送中断信号,但是不一定能中断成功,这取决于业务代码是否具有中断能力。

5、中断在计算机中具有非常重要的意义,分为软中断,硬中断,可屏蔽中断,不可屏蔽中断,很有意思。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

吕哥架构

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

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

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

打赏作者

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

抵扣说明:

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

余额充值