欢迎来到第二集。
如何正确停止线程,讲解原理:使用interrupt来通知,而不是强制
java中对线程的停止并没有一个类似于电脑菜单关机那么个特别理想的命令,而是让一个线程使用intterrupt来停止目标线程,但是这个intterrupt只是一个通知并不是强制命令,因为目标线程是一个独立的其他人创建的线程,它需要完成本身的逻辑任务才能停止,但是这个过程只有它自己最清楚,目标线程的停止实际上就是它自己来决定什么时候停止,不是强制的,intterrupt是打断的意思而不是停止的意思,是因为调用interrupt的线程不清楚目标线程是否执行完毕需要停止,只是发号命令通知中断,具体停止操作还是目标线程决定。
通常线程停止有两种情况,第一就是run方法执行完毕,第二是发生异常并且没有捕获。
package threadcoreknowledge.stopthreads;
/**
* @author bril
* 描述: run方法内没有sleep或wait方法时,停止线程
*/
public class RightWayStopThreadWithoutSleep implements
Runnable{
@Override
public void run() {
int num = 0;
while(num <= Integer.MAX_VALUE / 2){
if(num % 10000 == 0){
System.out.println(num+"是10000的倍数");
}
num++;
}
System.out.println("线程结束!");
}
public static void main(String[] args) {
Thread thread = new Thread(new RightWayStopThreadWithoutSleep());
thread.start();
}
}
结果是:
。。。。
1073700000是10000的倍数
1073710000是10000的倍数
1073720000是10000的倍数
1073730000是10000的倍数
1073740000是10000的倍数
线程结束!
线程执行完毕可以看到num最大为1073740000
再看下在阻塞状态停止线程:
package threadcoreknowledge.stopthreads;
/**
* @author bril
* 带有sleep的中断线程的写法
*/
public class RightWayStopThreadWithSleep {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = () -> {
int num = 0;
try {
while(!Thread.currentThread().isInterrupted() &&
num <= 300){
if(num % 100 == 0){
System.out.println(num+"是100的倍数");
}
num++;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(runnable);
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
结果:
0是100的倍数
100是100的倍数
200是100的倍数
300是100的倍数
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at threadcoreknowledge.stopthreads.RightWayStopThreadWithSleep.lambda$0(RightWayStopThreadWithSleep.java:19)
at java.lang.Thread.run(Thread.java:745)
上边代码1000大于500所以当执行到intterupt的时候线程处于阻塞状态,这时第一个sleep会抛出异常并且被捕获,这样也就停止了线程,这种方式是异常方式停止而不是判断intterrupt停止。
接下来看线程在每次迭代后都阻塞的情况:
package threadcoreknowledge.stopthreads;
/**
* @author bril
* 执行过程中,每次循环都会调用sleep或wait等方法,
* 那么不需要每次迭代都检查是否中断
*
*/
public class RightWayStopThreadWithSleepEveryLoop {
public static void main(String[