关闭一个线程的正确姿势

x33g5p2x  于2022-02-28 转载在 其他  
字(2.1k)|赞(0)|评价(0)|浏览(120)

一 点睛

JDK 有一个  stop 方法,但该方法早就弃用,并不推荐,这里介绍其他关闭线程的方法。

二 线程结束生命周期正常结束

线程运行结束, 完成了自己的使命之后,就会正常退出,如果线程中的任务耗时比较短,或者时间可控,那么放任它正常结束就好了。

三 捕获中断信号关闭线程

通过 new Thread 的方式创建线程,这种方式看似简单,其实它的派生成本是比较高的,因此在一个线程中往往会循环地执行某个任务,比如心跳检查,不断地接受网络消息报文等,系统决定退出的时候,可以借助中断方式使其退出。

1 代码

package concurrent;

import java.util.concurrent.TimeUnit;

public class InterruptThreadExit {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("I will start work");
                while (!isInterrupted()) {
                    // 我在工作
                }
                System.out.println("I will be exiting");
            }
        };
        thread.start();
        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("system will be shutdown");
        thread.interrupt();
    }
}

2 测试结果

I will start work

system will be shutdown

I will be exiting

上面代码中通过检查线程中断标识来决定线程是否退出,如果在线程中执行某个可中断方法,则可以通过捕获中断信号来决定是否退出线程

3 代码

package concurrent;

import java.util.concurrent.TimeUnit;

public class InterruptThreadExit1 {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("I will start work");
                for (; ; ) {
                    // 我在工作
                    try {
                        TimeUnit.MILLISECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        break;
                    }
                }
                System.out.println("I will be exiting");
            }
        };
        thread.start();
        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("system will be shutdown");
        thread.interrupt();
    }
}

4 测试结果

I will start work

system will be shutdown

I will be exiting

四 使用 volatile 开关控制

由于线程的中断标识很可能被擦除,或者线程逻辑单元中不会调用任何可中断方法,所以使用 volatile 修饰的开关 flag 关闭线程也是一种常用的做法。

1 代码

package concurrent;

import java.util.concurrent.TimeUnit;

public class InterruptThreadExit2 {
    static class MyTask extends Thread {
        private volatile boolean closed = false;

        @Override
        public void run() {
            System.out.println("I will start work");

            while (!closed && !isInterrupted()) {
                // 我在工作
            }
            System.out.println("I will be exiting");
        }

        // 关闭线程方法
        public void close() {
            this.closed = true;
            this.interrupt();
        }
    }

    public static void main(String[] args) {
        MyTask task = new MyTask();
        task.start();
        try {
            TimeUnit.SECONDS.sleep(6);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("system will be shutdown");
        task.close();
    }
}

2 测试

I will start work

system will be shutdown

I will be exiting

相关文章