多线程-如何优雅的关闭正在运行的线程

156 阅读2分钟

1-调用stop方法,该方法不建议使用,这种方法会强制关闭线程,不会管线程中的数据状态,也不会去处理数据的中间态,造成数据的不一致。

public static void main(String[] args) {
    Thread thread = new Thread(()->{
        while (true){
            System.out.println("go on ");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }
    });
    thread.start();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {

    }
    thread.stop();
}

2-suspend方法(暂停).resume方法(恢复),该方法也不建议使用。对于waiting状态和block状态的线程是无法处理的。当缺少了resume方法的调用的时候,会一直持有锁,不会释放锁。导致死锁问题.同时也会出现与stop方法相同的问题,出现数据的不一致。


public static void main(String[] args) {
    Thread thread = new Thread(()->{
        while (true){

            System.out.println("go on ");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

            }
        }
    });
    thread.start();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {

    }
    //暂停
    thread.suspend();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {

    }
    //重启
    thread.resume();
}

3-使用volatile修饰变量控制,无法精细化控制,当状态变成了结束的时候,上一个线程检测到结束的标记,结束线程时,无法保证线程执行的方法内,数字的值与外部预判的值一致,也就是说打断时间没有办法精细化控制。

public volatile static  Boolean flag = true;
public static void main(String[] args) {
    Thread thread = new Thread(()->{
    long i =0;
        while (flag){
               i++;
            
            
        }
        System.out.println("i:= " + i);
    });
    thread.start();
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {

    }
   flag = false;
}

4-interrupt()and isInterrupted(比较优雅)-通过判断线程的interrpute状态来判断线程的结束,同时也能通过捕获对应的wait和block的状态所抛出的异常,来处理对应状态下的业务逻辑。

public static void main(String[] args) {
    Thread thread = new Thread(()->{
        long i =0;
        
        while (!Thread.interrupted()){
            i++;
        }
        System.out.println("i:=" +  i);

    });
    thread.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {

    }
    thread.interrupt();
}

总结:关闭线程的方法有三大类 1.自然结束(能自然结束的尽量自然结束) 2.使用stop(),suspend(),resume()方法 3.使用volatile标志位 3.1有些场景不符合使用(存在线程阻塞的情况,导致无法进入下一次的循环判断标志位) 3.2无法精确控制,当循环内执行累加操作时,外部控制的标志位的变更无法准确的停止到指定数据的累加 4.使用interrupted()和interrupt()方法是比较优雅的。 通过线程本身的状态位去结束,同时也能解决标志的阻塞问题,通过捕获对应的异常做相应的处理即可。