6.4 ThreadPoolExecutor線程池的關閉方法shutdown和shutdownNow區別、示例

shutdown():

把線程池的狀態設置成SHUTDOWN狀態,然後中斷所有沒有正執行任務的線程

shutdownNow():

首先把線程池的狀態設置成STOP,然後嘗試停止所有正在執行任務或者暫停任務的線程,並返回等待執行任務的列表

常用

通常我們調用shutdown()方法關閉線程池,如果不需要任務執行完成,可以調用shutdownNow()

原理

遍歷線程池中的工作線程,然後組個調用線程的interrupt方法來中斷線程,所以無法響應中斷任務的可能永遠無法停止

其他方法

isShutdown():

只要調用了shutdown或者shutdownNow,isShutdown就會返回true,否則false

isTerminaed():

當所有任務關閉之後,才表示線程池關閉成功,這時會返回true

isTerminating:

執行了shutdown或shutdownNow之後,還有任務正在進行中=true,沒有任務進行中=false

測試示例

測試shutdown

public class Test {
    static class Customer extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "開始執行");
            try {
                //模擬任務執行4s
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "執行完成");
        }
    }

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

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10,
                20,
                20,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(10), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                //1、設置線程的名字
                Thread thread = new Thread(r);
                //thread.setName("通過自定義線程工廠誰知線程名字");
                //2、設置成守護線程
                //thread.setDaemon(true);
                return thread;
            }
        },
                //四種阻塞隊列滿之後的處理方式
//                new ThreadPoolExecutor.CallerRunsPolicy()); 使用調用線程處理,比如是main調用的線程池,用main線程執行
//                new ThreadPoolExecutor.DiscardOldestPolicy());把阻塞隊列首元素丟掉,執行當前線程
//                new ThreadPoolExecutor.DiscardPolicy());直接丟掉當前線程
                new AbortPolicy());//跑出異常

        executor.execute(new Customer());
        Thread.sleep(100);
        //當前線程還未執行完,執行shutdown
        System.out.println("執行shutdown之前");
        System.out.println(executor.isTerminated());
        System.out.println(executor.isShutdown());
        System.out.println(executor.isTerminating());

        executor.shutdown();
        System.out.println("執行shutdown之後,但是還有任務正在執行");
        //線程還沒有執行完成,isTerminated()=false
        System.out.println(executor.isTerminated());
        System.out.println(executor.isShutdown());
        System.out.println("有任務進行中isTerminating="+executor.isTerminating());

        //線程執行完成,isTerminated()=true
        Thread.sleep(4000);
        System.out.println("執行shutdown之後,所有任務執行完成");
        System.out.println(executor.isTerminated());
        System.out.println("沒有任務進行中isTerminating="+executor.isTerminating());
    }
}

結果

Thread-1開始執行
執行shutdown之前
false
false
false
執行shutdown之後,但是還有任務正在執行
false
true
有任務進行中isTerminating=true
Thread-1執行完成
執行shutdown之後,所有任務執行完成
true
沒有任務進行中isTerminating=false

測試shutdownNow

public class Test {
    static class Customer extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "開始執行");
            try {
                //模擬任務執行4s
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "執行完成");
        }
    }

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

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10,
                20,
                20,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(10), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                //1、設置線程的名字
                Thread thread = new Thread(r);
                //thread.setName("通過自定義線程工廠誰知線程名字");
                //2、設置成守護線程
                //thread.setDaemon(true);
                return thread;
            }
        },
                //四種阻塞隊列滿之後的處理方式
//                new ThreadPoolExecutor.CallerRunsPolicy()); 使用調用線程處理,比如是main調用的線程池,用main線程執行
//                new ThreadPoolExecutor.DiscardOldestPolicy());把阻塞隊列首元素丟掉,執行當前線程
//                new ThreadPoolExecutor.DiscardPolicy());直接丟掉當前線程
                new AbortPolicy());//跑出異常

        executor.execute(new Customer());
        Thread.sleep(100);
        //當前線程還未執行完,執行shutdown
        System.out.println("執行shutdown之前");
        System.out.println(executor.isTerminated());
        System.out.println(executor.isShutdown());
        System.out.println(executor.isTerminating());

        executor.shutdownNow();
        System.out.println("執行shutdown之後,但是還有任務正在執行");
        //線程還沒有執行完成,isTerminated()=false
        System.out.println(executor.isTerminated());
        System.out.println(executor.isShutdown());
        System.out.println("有任務進行中isTerminating="+executor.isTerminating());

        //線程執行完成,isTerminated()=true
        Thread.sleep(4000);
        System.out.println("執行shutdown之後,所有任務執行完成");
        System.out.println(executor.isTerminated());
        System.out.println("沒有任務進行中isTerminating="+executor.isTerminating());
    }
}

結果:因爲要中斷正在執行的任務,所有會報中斷異常

Thread-1開始執行
執行shutdown之前
false
false
false
執行shutdown之後,但是還有任務正在執行
false
true
有任務進行中isTerminating=true
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at cn.enjoyedu.ch6.Test$Customer.run(Test.java:14)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:748)
Thread-1執行完成
執行shutdown之後,所有任務執行完成
true
沒有任務進行中isTerminating=false

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章