内涵.终止/打断一个线程
(一).原则
让一个线程停止运行,也就是销毁
在java中,要终止一个线程,做法想相对唯一,就是让run方法尽快执行结束,也就是说不会马上强行终止线程.
(二).方法
方法一:手动创造一个标志位,作为run的执行结束的条件
例:
当线程任务中存在循环,设置一个标志位 isQuit 来终止循环,代码如下:
public class Demo8 {
private static boolean isQuit = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while (!isQuit){
System.out.println("线程工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("工作完成!");
});
t.start();
Thread.sleep(3000);
isQuit = true;
System.out.println("设置isQuit为true");
}
}
执行情况为:
注意:此时 isQuit 是成员变量,如果改成局部变量,那结果会发生变化吗???
答案是肯定的!!
可以看到idea报错,报错信息为
意思为:lambda表达式中使用的变量应该是final或有效的final
原因为:lambda表达式中有 变量捕获的语法,就是把当前的作用域中的变量在lambda中复制了一份,
在java中变量捕获语法有个前提,必须捕获一个final,或者实际上是final的变量.
所以我们可以添加isQuit的限制,加上final,或者删掉后面代码修改isQuit的代码,达到实际上是final的条件,错误就会消失,但是这样显然不是我们想要的结果!!!!
所以,我们选择手动创建一个标志位时,创建isQuit为成员变量,lambda对于这个标识位不在是捕获语法,而是内部类访问外部类属性,则不会出现final的限制了
上述代码不够优雅!!
1.需要手动创建变量
2.当线程内部sleep时,主线程修改变量,线程内部不能及时响应
所以我们引入第二个方法!!
方法二.利用Tread内部的标志位 isInterrupted与interrupt
我们先看下面的代码:
public class Demo9 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
System.out.println("线程工作中");
}
System.out.println("线程结束");
});
t.start();
Thread.sleep(100);
t.interrupt();
System.out.println("让线程t终止");
}
}
没错结果为:
确实实现了标识位的作用,但是如果线程中有sleep呢???观察下面代码
public class Demo9 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
while(!Thread.currentThread().isInterrupted()){
System.out.println("线程工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程结束");
});
t.start();
Thread.sleep(100);
t.interrupt();
System.out.println("让线程t终止");
}
}
结果变成:
正常sleep休眠时间到,才能被唤醒,而此时interrupt可以使sleep内部出发一个异常,从而提前唤醒,但是线程t仍然继续工作,并没有结束
interrupt唤醒线程之后,此时sleep方法抛出异常,同时自动清除刚刚的标识位
为啥会有这种设定呢?
java希望线程收到"中断信息"时,程序员决定接下来怎么处理
所以接下来我们可以这样做:
执行结果好处显而易见:
让程序员对线程有更大的"操作空间",但是如果没有sleep,则不会有上述操作的空间