停止线程,也许我们首先会有一种错感,觉得使用Thread.stop()或者Thread.interrupt()与Thread.interrupted()等组合就能退出线程了。可是在实际运用过程中,这样真的可以达到安全退出线程吗?下面就由我带大家逐一分析实例,最后顺便举个例说明如何才能安全的退出线程。
1、Thread.stop()方式停止线程,会发生什么呢?
不用多说,直接简单粗暴的方式,肯定就是直接上代码啦,如图:
通过运行结果:可以看到执行stop()方法退出线程,会无法预料到线程到底执行到哪一步就被意外终止了,从而无法保证执行完一个完成操作流程(比如:循环体一次自上而下的逻辑过程),所以属于非法终止线程。该方法已被废弃,不推荐使用。
2、Thread.interrupt()方式停止线程,又会发生什么呢?
继续简单粗暴吧,分情况讨论:
情形1:当线程没有阻塞时,可以正常退出线程(注意注释部分代码)
package com.xxl.job.myThread;
public class WrongStopThread extends Thread {
public static void main(String[] main) {
WrongStopThread wrongStopThread = new WrongStopThread();
wrongStopThread.setName("myThread");
System.out.println("线程开始启动......");
wrongStopThread.start();
try {
Thread.sleep(1000); //休眠一下,模拟效果;否则无法进入线程循环体
} catch (InterruptedException e) {
e.printStackTrace();
}
wrongStopThread.interrupt(); //停止线程
System.out.println("main application已结束!");
}
@Override
public void run() {
while(!this.isInterrupted()){ //这里相当于也是设置一个线程退出标志
System.out.println(this.getName() + ": is running .......");
/* try {
Thread.sleep(3000); //设置休眠3秒
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
System.out.println(this.getName() + ":线程已结束!");
}
}
流程能走完,线程可以正常的退出,运行结果:
情形2: 当注释部分代码块可用时,即
@Override
public void run() {
int count = 0;
while(!this.isInterrupted()){ //这里相当于也是设置一个线程退出标志
System.out.println(this.getName() + ": is running .......");
try {
Thread.sleep(3000); //设置休眠3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName() + ":count = " + count++);
}
System.out.println(this.getName() + ":线程已结束!");
}
运行结果抛出了异常,显示线程一直在跑,并没有结束:
具体原因可以看具体API文档说明:
由此可见, Thread.interrupt() 并不能保证线程能正常退出,也不建议采用来停止线程。
3、最后说一下如何安全停止线程,可采用通过设置volatile修饰的退出标志位来保证线程安全退出
不用多说,还是直接上代码
package com.xxl.job.myThread;
public class StopThread extends Thread {
volatile boolean isStop = false; //线程退出标志
@Override
public void run() {
int count = 0;
while(!isStop){ //安全退出判断
System.out.println(this.getName() + ": is running .......");
try {
Thread.sleep(1000); //设置休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName() + ":count = " + count++);
}
System.out.println(this.getName() + ":线程已结束!");
}
public static void main(String[] main) {
StopThread stopThread = new StopThread();
stopThread.setName("myThread");
System.out.println("线程开始启动......");
stopThread.start();
try {
Thread.sleep(1000); //休眠一下,模拟效果
} catch (InterruptedException e) {
e.printStackTrace();
}
//stopThread.stop(); //停止线程
stopThread.isStop = true; //停止线程
System.out.println("main application已结束!");
}
}
就这样,如有不恰当之处,请不吝赐教。