使用优雅方式结束线程

版权声明: https://blog.csdn.net/Dongguabai/article/details/84789255

方式一

设置一个是否结束的标志(开关)。

package com.example.threaddesign;

/**
 * @author Dongguabai
 * @date 2018/12/4 15:16
 */
public class StopThread1 {

    private static volatile boolean stop = true;

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(()->{
            while (stop){
                System.out.println("do sth-----");
            }
        });

        t1.start();
        Thread.sleep(10);
        stop();

    }

    public static void stop(){
        System.out.println("结束线程1111111");
        stop = false;
    }

}

方式二

结合 interrupt API。

package com.example.threaddesign;

/**
 * @author Dongguabai
 * @date 2018/12/4 15:16
 */
public class StopThread2 {

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    break;
                }
                System.out.println("do sth-----");
            }
        });

        t1.start();
        Thread.sleep(10);
        t1.interrupt();

    }

}

使用 interrupt API 也可以使用异常的方式去中断线程,比如可以让当前线程在循环中去 sleep(1),因为这样在执行 interrupt() 方法之后会抛出异常(具体可参看:https://blog.csdn.net/Dongguabai/article/details/82318002)。

但是可以发现方法一与方法二很局限,如果本身在工作的线程中本身就没有加开关,也没有监控是否中断呢,即本身的逻辑无法更改。在 JDK 中的 stop() 方法已经被建议不再使用。那么就可以采用将工作线程进行封装的方式。

方式三

使用 interrupt API + 守护线程的方式。主要应用了用户线程结束后守护线程自动退出的方式去暴力关闭。

package com.example.threaddesign;

import java.util.ArrayList;

/**
 * @author Dongguabai
 * @date 2018/12/4 15:33
 */
public class ThreadService {

    //执行线程
    private Thread executor;

    private boolean finished = false;

    public void execute(Runnable task) {
        executor = new Thread() {
            @Override
            public void run() {
                Thread runner = new Thread(task);
                runner.setDaemon(true);
                //使用守护线程去执行 task
                runner.start();
                try {
                    //如果任务执行完成了
                    runner.join();
                    //双重防护,如果在规定的超时时间内已经完成了
                    finished = true;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        executor.start();
    }

    public void shutdown(long mills) {
        long shutdownTime = System.currentTimeMillis();

        while (!finished) {   //双重防护,如果在规定的超时时间内已经完成了
            if (System.currentTimeMillis() - shutdownTime >= mills){
                System.out.println("任务超时,强制结束任务!");
                executor.interrupt();
                break;
            }
            /*try {
                executor.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("执行线程被打断。。。");
                e.printStackTrace();
                break;
            }*/
            //也可以不使用异常抛出的方式
            if (executor.isInterrupted()){
                System.out.println("执行线程被打断。。。");
                //执行线程已被中断
                break;
            }
        }
        finished = false;
    }
}

可以简单测试一下:

package com.example.threaddesign;

/**
 * @author Dongguabai
 * @date 2018/12/2 20:58
 */
public class ThreadTest {

    public static void main(String[] args) {

        System.out.println("任务开启");
        long start = System.currentTimeMillis();
        ThreadService ts = new ThreadService();
        ts.execute(() -> {
            while (true) {
                //假设不停的在工作,那就必然超时
            }
        });

        ts.shutdown(1000);
        long end = System.currentTimeMillis();
        System.out.printf("任务已被终止,共耗时【%s】", end - start);

    }


}

运行结果:

任务开启
java.lang.InterruptedException
任务超时,强制结束任务!
	at java.lang.Object.wait(Native Method)
	at java.lang.Thread.join(Thread.java:1245)
	at java.lang.Thread.join(Thread.java:1319)
	at com.example.threaddesign.ThreadService$1.run(ThreadService.java:26)
任务已被终止,共耗时【1051】

那假如任务 5s 就能结束,而我要求的是 10s,即任务提早结束。

package com.example.threaddesign;

/**
 * @author Dongguabai
 * @date 2018/12/2 20:58
 */
public class ThreadTest {

    public static void main(String[] args) {

        System.out.println("任务开启");
        long start = System.currentTimeMillis();
        ThreadService ts = new ThreadService();
        ts.execute(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        ts.shutdown(10000);
        long end = System.currentTimeMillis();
        System.out.printf("任务已被终止,共耗时【%s】", end - start);

    }


}

运行结果:

任务开启
任务已被终止,共耗时【5056】

猜你喜欢

转载自blog.csdn.net/Dongguabai/article/details/84789255