1. 如何停止一个线程?
官方停止线程的方法被废弃了,所以不能直接停止线程,这么做是非常不安全的。
2. 为什么不能简单停止一个线程?
因为,简单停止一个线程会出现很多异常情况,比如:多线程读取共享变量时,其中一个线程加锁了,其它线程处于等待状态,如果,将加锁线程暂停了,那么其它线程就会被堵塞在这里,不能释放,假如加锁线程在等待其它线程中某个线程的释放锁,那么,就会出现死锁。所以,线程中的暂停方法也被废弃了。如果,直接使用stop方法停止线程,线程立刻被回收,被堵塞的线程立刻获得锁权限并加锁,然后去操作共享变量,此时发现共享内存有一堆莫名数据或者状态,这些数据原因是前一个线程在被停止时立刻被回收了,没有来的及处理完成,就被其它线程获得加锁操作了,那么,这个线程也会出现异常,甚至Crash。
3. 如何安全的停止一个线程?
通过线程自行结束,而不是强行停止,目标线程应当具有处理中断能力。也是在使用线程过程中要通过结束任务从而停止线程。通过线程任务而停止线程,和停止线程结果上没什么区别,但是,和通过停止线程的方法结束线程的方式相比,结果有明显区别,停止线程是不安全的做法,而通过逻辑控制结束任务从而结束线程却是安全的做法。
通过逻辑中断线程的方式:
1. 使用Thread内置的interrupted()(中止)方法:
@FastNative
public static native boolean interrupted();
但是,在线程中要添加识别中止状态的逻辑:
Thread thread = new Thread() {
@Override
public void run() {
for (int idx = 0; idx < 1000000; idx++) {
// interrupted()
if (isInterrupted()) {
break;
}
// TODO: 2020/6/1
}
}
};
thread.start();
// 调用中断方法,发送中断线程状态
thread.interrupt();
获取中止状态的方法有两个,分别是isInterrupted()和interrupted(),其中interrupted()是静态方法,两个方法的区别:
isInterrupted():是简单的读取该线程的中断状态,不清空可以重复调用,直到状态清空前一直返回true。
interrupted():是静态方法,获取该线程的中断状态,并清空状态。中断状态调用后清空,后续再调用返回false。
2. volatile boolean 标志位,就是自己实现中断逻辑:
class InterruptThread extends Thread {
public volatile boolean isStopped = false;
@Override
public void run() {
super.run();
for (int idx = 0; idx < 100000; idx++) {
if (isStopped) {
return;
}
System.out.println("test");
}
}
}
void test() {
InterruptThread thread = new InterruptThread();
thread.start();
thread.isStopped = true
}