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

}