JAVA EE 多线程 --- 线程的终止

如何让线程结束 => 核心是让其run的方法提前结束 ! => 通过代码来控制 !

方法一: isQuit 来实现控制

首先我们先采用boolean类型的 [isQuit] 来对run进行控制 !

public class ThreadDemo8 {
    static boolean  isQuit = false;//首先设置为false,后面通过对其改变值来对线程的结束
    public static void main(String[] args) {
        Thread  thread = new Thread(()->{
            while (!isQuit){
                System.out.println("这是一个中断测试!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程结束!");
        });
        thread.start();

        try {
            Thread.sleep(3000);//运行3秒后线程将运行结束!
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("让线程结束!");
        isQuit = true;//改变值控制Thread中的while循环结束,实际也是结束了run方法!
    }
}

运行结果

这个过程很好的说明了对线程的有了中断处理! 

注意:

如果下方代码中的顺序调换可能就会出现"让线程结束!"与"线程结束!"顺序不确定哪个先出现!

   System.out.println("让线程结束!");
   isQuit = true;//改变值控制Thread中的while循环结束,实际也是结束了run方法!

原因是:无法确定Thread方法(Thread线程)中的先运行还是main方法(主线程)中的先运行 !‘

问题一:如果把isQuit 作为 main 方法中的局部变量,是否可行 ?

lambda表达式/匿名内部类是可以访问外面的定义的局部变量的!但是局部变量必须要用final来修饰,但是用final后变量是不可变了,但是后面要对该变量进行修改,所以行不通!

为什么Java对变量捕获有final的限制?

变量捕获:本质上就是传参,换句话说就是让lambda表达式在自己的栈帧中创建一个新的isQuit并把外面的isQuit值拷贝过来!

isQuit 是局部变量的时候是属于main方法的栈帧中的,但是Thread lambda 是有自己独立的栈帧的(在另外一个线程中的方法),二个栈帧的生命周期是不一致的!如果这样使用的话main的栈帧可能已经销毁,但是Thread的栈帧还在此时它还想调用isQuit不是就出问题了,Java中为了避免isQuit不同步,就干脆把不让你对该值进行修改,这就是为什么Java对变量捕获有final的限制!

方法二: isInterrupted 来实现控制

刚刚的方法可能不是特别的高大上,接下来我们换一个方法 (通过Thread类中的方法)来解决!

public class ThreadDemo9 {
    public static void main(String[] args) {
        Thread  thread = new Thread(()->{
            while (!Thread.currentThread().isInterrupted()){ //代替了!isQuit
                //Thread.currentThread()获取当前实例的作用!
                System.out.println("这是一个中断测试!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;//为了顺利让线程结束!
                }
            }
            System.out.println("线程结束!");
        });
        thread.start();

        try {
            Thread.sleep(3000);//运行3秒后线程将运行结束!
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("让线程结束!");
        thread.interrupt();//代替了isQuit = true;
    }
}

运行结果

  注:想要下面不抛异常,可以删除catch中的 e.printStackTrace()代码即可 !

还是依旧可以对线程进行中断!这个更加的利用了Thread中的方法,更加的精简与高大上!

问题二:Break在代码中的作用分析!

使用break的作用是为了让代码线程可以顺利的结束 !当执行interrupt()之后已经将值改变为true,由于Thread的中的sleep方法可能会被提前唤醒!导致清除了Thread对象的isInterrupted的标志位,值变回了false,导致线程无法结束,这里可以设置break可以强制线程结束!

提前唤醒的原因:就是可能interrupt()方法执行后Thread中的sleep本来应该在1秒被唤醒,结果在0.8秒的时候提前被唤醒了!

sleep被提前唤醒后会进行的操作:1.抛出interruptedException(紧接着就会被catch获取到)

                                                        2.清除Thread 对象的isInterrupted的标志位!

   

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

追鸣--守仰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值