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 }