写于:2020-02-09

一、废弃的方法 Thread.stop :不推荐使用

01.jpg
java 官方文档提到该方法已经废弃,并提到废弃原因:通过该方法停止线程,线程可能不会释放被线程占用的所有锁。

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

线程运行结束,就会正常退出,如果线程中的任务耗时比较短或者时间可控,直接放任其自行结束。

三、捕获中断信息关闭线程

通过捕获中断信号,结束线程,案例如下:

  1. public class SimpleThread {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread thread = new Thread(){
  4. @Override
  5. public void run() {
  6. System.out.println("准备开始执行任务");
  7. while (!isInterrupted()){ // 该方法不会复位标志位
  8. // todo
  9. // 存在的问题:如果这里夯住了,即使发送了中断,也无法中断线程运行
  10. }
  11. System.out.println("任务执行结束");
  12. }
  13. };
  14. thread.start();
  15. TimeUnit.MILLISECONDS.sleep(10);
  16. System.out.println("============任务即将结束");
  17. thread.interrupt();
  18. }
  19. }

通过中断标识来进行线程是否关闭的控制。

该方式存在问题,如果在 while 循环的执行逻辑夯住了,此时线程便无法结束生命周期

四、通过 volatile 开关控制

代码案例如下:

  1. public class SimpleThread {
  2. public static void main(String[] args) throws InterruptedException {
  3. MyTask thread = new MyTask();
  4. thread.start();
  5. TimeUnit.MILLISECONDS.sleep(10);
  6. System.out.println("============任务即将结束");
  7. thread.close();
  8. }
  9. public static class MyTask extends Thread{
  10. // 开关
  11. private volatile boolean closed = false;
  12. @Override
  13. public void run() {
  14. System.out.println("准备开始执行任务");
  15. while (!closed && !isInterrupted()){ // 该方法不会复位标志位
  16. // todo
  17. // 存在的问题:如果这里夯住了,即使发送了中断,也无法中断线程运行
  18. }
  19. System.out.println("任务执行结束");
  20. }
  21. public void close(){
  22. this.closed = true;
  23. this.interrupt();
  24. }
  25. }
  26. }

该方式存在问题,如果在 while 循环的执行逻辑夯住了,此时线程便无法结束生命周期

五、通过守护线程的方式关闭线程:强制线程停止

public class SimpleThread {
    public static void main(String[] args) throws InterruptedException {
        ThreadService threadService = new ThreadService();
        threadService.execute(()->{
            //1-模拟任务被 夯住了
            while (true){
            }
        });
        TimeUnit.SECONDS.sleep(10);
        // 通过结束executeThread 来实现强制中断任务线程
        threadService.shutdown();
    }
    public static class ThreadService{
        /** 执行线程 **/
        private Thread executeThread;
        /** 是否执行结束:true 是,false 否 **/
        private boolean finished = false;

        /** 执行逻辑 **/
        public void execute(Runnable runnable){
            executeThread = new Thread(){
                @Override
                public void run() {
                    Thread runner = new Thread(runnable);
                    runner.setDaemon(true); // 设置为守护线程,executerTHread 结束守护线程一起结束
                    runner.start();
                    try {
                        runner.join(); // 等待 runner 执行结束,才会执行 executerThread 线程逻辑
                        finished = true;
                    } catch (InterruptedException e) {
                        // 中断线程,使得守护线程一样跟着结束
                        e.printStackTrace();
                    }
                }
            };
            executeThread.start();
        }

        /**
         * 强制停止线程
         */
        public void shutdown(){
            while (!finished){
                executeThread.interrupt();
                break;
            }
            finished = true;
        }
    }
}

通过中断线程,使得守护线程也中断来达到强制中断任务线程的目的。