007 优雅的关闭线程

一 .概述

 在jdk之中之前又一个stop方法可以关闭线程,但是那个方法存在线程安全的问题,现在已经被废除掉了.

之后就没有出现关闭线程的方法了.

但是在我们的使用过程之中,我们需要关闭线程,这个时候,我们就需要用其它的方式来完成线程的关闭操作.


二 . 使用标记位完成

public class StopThread {

    private static class task implements Runnable {
        // 标记位
        private volatile boolean flag = true;

        public void run() {
            while (flag) {
                System.out.println("running ...");
            }
        }

        public void shutdown() {
            this.flag = false;
        }
    }

    public static void main(String[] args) throws Exception {
        task task = new task();
        Thread thread = new Thread(task);
        thread.start();
        // 主线程休眠三秒之后 修改标记位
        TimeUnit.SECONDS.sleep(3);
        task.shutdown();
    }
}

以上的方式时可以完成任务的,但是需要不断的监听标记位.


三 . 使用interrupt的方式

public class InterruptThread {

    private static class Task implements Runnable {
        public void run() {
            try {
                for (;;) {
                    TimeUnit.MICROSECONDS.sleep(100);
                    System.out.println("thread is running ... ");
                }
            } catch (Exception e) {
                return ; 
            }

        }
    }

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Task());
        thread.start();
        // 主线程休眠3秒之后,主动打断任务线程
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    }
}

在主线程休眠3秒之后,主动打断子线程,子线程的sleep方法会抛出异常我们捕获异常就能终止线程的运行了.

在这里我们使用的是sleep方法,同时我们也可以用判断的方式.

public class InterruptThread {

    private static class Task implements Runnable {
        public void run() {
            for (;;) {
                // TimeUnit.MICROSECONDS.sleep(100);
                if (!Thread.interrupted())
                    System.out.println("thread is running ... ");
                else
                    return;
            }

        }
    }

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Task());
        thread.start();
        // 主线程休眠3秒之后,主动打断任务线程
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    }
}

相对来说,我们用判断的方式还是比较好的.


四 .暴力停止线程

当我们的任务花费的时间比较长的时候,我们的循环判断是根本没有触发的时候,这个时候我们就需要使用暴力的方式强制线程停止.

public class ThreadService {
    //执行线程,相当于一个主线程...
    private Thread executeThread;

    public void startThread(final Runnable task) {
        // 创建执行线程,这个线程就是一个主线程
        executeThread = new Thread() {
            @Override
            public void run() {
                // 开启子线程
                Thread childThread = new Thread(task);
                // 设置子线程为守护进程
                childThread.setDaemon(true);
                // 开启子线程的任务
                childThread.start();
                // 父线程一直线循环
                try {
                    //主线程一直让子线程运行
                    childThread.join();
                    
                } catch (InterruptedException e) {
                    // 当主线程被打断的时候,直接终止自己的运行
                    // nothing to do
                    System.out.println("收到了终结主线程的信号了,现在我需要停止了");
                    System.out.println("我带的守护线程也需要终结了..");
                    return ; // 终结主线程,子线程随之被杀死
                }
            }
        };
        //开启执行线程
        executeThread.start();
    }

    public void shutdown() {
        // 打断主线程 --那么守护进程就被终结了
        this.executeThread.interrupt();
    }
}

我们创建了一个线程服务类,这个服务类由两个方法

[1]开启一个线程

[2]终结一个线程

原理 :  在这个线程类里面有有一个执行线程,在开启的时候会初始化这个线程任务,这个线程任务很简单.

    [1] 创建一个子线程,将线程逻辑交给子线程.其中子线程被设置为守护线程.

    [2]然后主线程自己阻塞,直到子线程运行完成或者自己的阻塞被打断.

我们的shutdown方法的实现很简单,那就是直接打断执行线程的阻塞状态.一旦执行贤臣被打断,会进入catch语句,语句里面会终结这个函数,那么子线程也被终止了.


五 .总结

现在我们看到线程的终结还需要自己去封装一个服务,到后面我们可以看到大神

李狗的代码,看它是如何解决这种问题的.

这里只是练习一下API而已.    

  

猜你喜欢

转载自www.cnblogs.com/trekxu/p/8970849.html
007
今日推荐