java并发编程之正确地终止一个线程interrupt/interrupted

以下demo是错误的终止线程的demo(使用thread.stop()方法实现终止线程):

public class ErrorStopThreadDemo {

    public static void main(String[] args) {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程终止结束");
            }
        });
        thread.start();
        thread.stop();
    }
}

输出结果:
在这里插入图片描述
说明:

  1. 使用thread.stop方法来终止线程就类似于在linux系统中使用 kill -9 pid进行进程的终止,这种终止线程的方式不管线程是否执行完毕就直接终止线程。是不正确的,所以输出的结果中没有输出“线程终止结束”几个字。

线程友好终止的前提条件时线程执行的逻辑要完全执行结束。

以下是正确地终止线程的方法一Demo:

public class CorrectStopThreadDemo1 {
    volatile boolean stop = false;

    public static void main(String[] args) {
        CorrectStopThreadDemo1 demo1 = new CorrectStopThreadDemo1();

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {

                while (!demo1.stop){

                }

                System.out.println("线程结束");
            }
        });
        thread.start();
        demo1.stop = true;
    }
}

执行结果:
在这里插入图片描述
说明:

  1. 这种中断线程的方法是根据一个标志变量stop变量进行是否终止。
  2. 因为stop使用了volatile 关键字修饰,所以具有可见性,主线程对它的修改立即被线程thread看见,然后就跳出while循环,执行后面的语句,友好地终止线程。

以下是正确地终止线程的方法2Demo:

首先介绍一下thread.interrupt()方法:
作用:当其它线程调用当前线程的interrupt方法,表示向当前线程打个招呼,告诉它中断线程可以执行了,至于什么时候中断,取决于当前线程自己。

public class CorrectStopThreadDemo2 {

    public static void main(String[] args) {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //实际上是修改中断标志位,与方法1类似,不过这个标志位是在JVM中维护的。
                //调用interrupt方法会使isInterrupted返回true。跳出while循环。
                while (!Thread.currentThread().isInterrupted()){

                }
                System.out.println("终止线程");
            }
        });
        thread.start();
        //主线程调用thread线程的interrupt方法,告诉thread线程中断线程可以执行了。
        thread.interrupt();
    }
}

执行结果:
在这里插入图片描述
说明:

  1. interrupt方法再改终止方法中的作用是修改标志位。使得程序跳出循环,正确终止。

线程终止的意义:

  1. 对正常的任务进行线程终止没有意义。
    有意义的终止线程的场景:
  2. while循环:通过一个终止标志位来实现线程的终止。
  3. 线程要处于阻塞状态下进行终止才有意义。
  4. Thread.join() Thread.sleep() obj.wait() 这些方法会导致线程阻塞,在一定的业务场景下对其进行正确的终止是有意义的。

以下是对 thread.join,Thread.sleep() obj.wait() 方法进行正确终止的demo:

public class CorrectStopThreadDemo3 {

    public static void main(String[] args) {
        CorrectStopThreadDemo3 demo3 = new CorrectStopThreadDemo3();
        demo3.stopWait();
        demo3.stopSleep();
        demo3.stopJoin();
    }



    public void stopSleep(){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //睡500秒
                    TimeUnit.SECONDS.sleep(500);
                } catch (InterruptedException e) {
                 //调用该线程的interrupt方式会抛出InterruptedException异常,
                 //然后被这里捕获到,然后执行余下代码
                    e.printStackTrace();
                }
                System.out.println("线程终止");
            }
        });
        thread.start();
        //不想线程执行那么久将其终止。
        thread.interrupt();

    }

    public void stopWait(){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this){
                    try {
                        //睡500秒
                        this.wait();
                    } catch (InterruptedException e) {
                     //调用该线程的interrupt方式会抛出InterruptedException异常,
                     //然后被这里捕获到,然后执行余下代码
                        e.printStackTrace();
                    }
                    System.out.println("线程终止");
                }

            }
        });
        thread.start();
        //不想线程执行那么久将其终止。
        thread.interrupt();
    }

 public void stopJoin(){

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        thread.interrupt();
    }
   }

执行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

说明:

  1. 这种方法的终止是通过执行当前线程的interrupt方法抛出了一个InterruptedException异常,然后执行异常代码块,然后执行下面的逻辑代码,正确终止线程。

Thread.interrupted()方法解释:

作用:
对设置中断标志的线程复位默认值,并且返回当前中断状态。

public class InterruptedDemo {

    public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("没有执行interrupt方法的中断标志值="+Thread.currentThread().isInterrupted());

                Thread.interrupted();

                System.out.println("没有执行interrupt方法然后复位后的中断标志值="+Thread.currentThread().isInterrupted());
                while (!Thread.currentThread().isInterrupted()){

                }
                System.out.println("执行了interrupt方法的中断标志值="+Thread.currentThread().isInterrupted());

                Thread.interrupted();
                System.out.println("执行了interrupt方法后复位后的中断标志值="+Thread.currentThread().isInterrupted());
            }
        });
        thread.start();
        //这里睡眠1s是为了把线程的while循环之前的代码执行完。
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
    }
}

执行结果:
在这里插入图片描述
说明:

  1. 没有执行interrupt方法时,中断标志默认false,所以第一个输出为false。
  2. 没有执行interrupt方法却使用了interrupted方法复位,中断标志恢复默认false,所以第二个输出为false。
  3. 执行了interrupt方法却没有使用interrupted复位时,中断标志被设置为true。所以第三个输出true。
  4. 执行了interrupt方法后使用interrupted复位时,中断标志被复位为false,所以第四个输出false。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值