如何正确停止线程
(想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)
1. 讲解原理
原理介绍:使用interrupt来通知,而不是强制。
Java中停止线程的原则是什么?
在Java中,最好的停止线程的方式是使用中断interrupt, 但是这仅仅是会通知到被终止的线程“你该停止运行了”,被终止的线程自身拥有决定权(决定否、以及何时停止),这依赖于请求停止方和被停止方都遵守一种约定好的编码规范。
任务和线程的启动很容易。在大多数时候,我们都会让它们运行直到结束,或者让它们自行停止。然而,有时候我们希望提前结束任务或线程或许是因为用户取消了操作,或者服务需要被快速关闭,或者是运行超时或出错了。
要使任务和线程能安全、快速、可靠地停止下来并不是一件容易的事。Java没有提供任何机制来安全地终止线程。但它提供了中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程的当前工作。
这种协作式的方法是必要的,我们很少希望某个任务、线程或服务立即停止,因为这种立即停止会使共享的数据结构处于不一致的状态。相反,在编写任务和服务时可以使用一种协作的方式当需要停止时,它们首先会清除当前正在执行的工作然后再结束。这提供了更好的灵活性,因为任务本身的代码比发出取消请求的代码更清楚如何执行清除工作。
生命周期结束(End- of-Lifecycle)的问题会使任务、服务以及程序的设计和实现等过程变得复杂,而这个在程序设计中非常重要的要素却经常被忽略。一个在行为良好的软件与勉强运的软件之间的最主要区别就是行为良好的软件能很完善地处理失败、关闭和取消等过程。
本章将给出各种实现取消和中断的机制,以及如何编写任务和服务,使它们能对取消请求做出响应。
2. 最佳实践:如何正确停止线程
2.1 线程通常会在什么情况下停止
1、run()方法运行完毕
2、 有异常出现,并且线程中没有捕获。
线程停止以后,所占用的资源会被jvm回收。
2.2 正确的停止方法:interrupt
2.2.1 通常情况下如何停止
package stopthreads;
/**
* 描述: run()方法内没有sleep()和wait()方法时,停止线程。
*/
public class RightStopThreadWithoutSleep implements Runnable{
public static void main(String[] args) {
Thread thread = new Thread(new RightStopThreadWithoutSleep());
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
@Override
public void run() {
int num = 0;
while (num <= Integer.MAX_VALUE / 2){
if (!Thread.currentThread().isInterrupted() && num % 10000 == 0) {
System.out.println(num + "是10000的倍数");
}
num++;
}
System.out.println("任务结束了。");
}
}
注意: thread.interrupt();
无法强制的中断线程,必须有要被中断的线程的配合。
即:需要在子线程中加上如下代码:!Thread.currentThread().isInterrupted()
2.2.2 线程可能被阻塞如何停止
package stopthreads;
import static java.lang.Thread.*;
public class RightStopThreadWithSleep {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = ()->{
int num = 0;
while (num <= 300){
if (num % 100 == 0 && !currentThread().isInterrupted()){
System.out.println(num + "是100的整数倍");
}
num++;
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(runnable);
thread.start();
Thread.sleep(500);
thread.interrupt();
}
}
结果如下:
2.2.3 如果线程在每次迭代后都阻塞
package stopthreads;
import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;
/**
* 描述:如果在执行过程中,每次循环都会调用sleep()或wait()等方法,那么...
*/
public class rightStopThreadWithSleepEveryLoop {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = ()->{
int num = 0;
try {
while (num <= 10000){
if (num % 100 == 0 && !currentThread().isInterrupted()){
System.out.println(num + "是100的整数倍");
}
num++;
sleep(10);
}
}catch (InterruptedException e){
e.printStackTrace();
}
};