Java併發編程(6)-ThreadPoolExecutor解讀(1)


在上文中已經寫過Executor線程調度框架的使用及幾種線程池,它們是整個Java併發編程的核心內容;本文將繼續講解和Executor一樣重要的自定義線程池,它能讓我們自己去定義一個多線程的執行者擁有的線程核心數、最大線程數、空閒線存活時間等。
本篇總結自《Java併發編程實踐》第八章 應用線程池 ,以及相關博客,想要更加深入瞭解的同學建議閱讀該書。

一、什麼是ThreadPoolExecutor

ThreadPoolExecutor位於java.util.concurrent併發包下,爲一些Executor提供了基本的實現,在JDK1.5中由Executors中的工廠中的newCachedThreadPoolnewFixedThreadPoolnewScheduledThreadExecutor方法所返回。但在JDK1.7之後,不能通過Executors去獲得ThreadPoolExecutor了,而是需要自己手動去定製。ThreadPoolExecutor是一個靈活的、健壯的池實現,允許用戶進行各種各樣的定製

二、ThreadPoolExecutor構造方法參數

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,//可不設置
                              RejectedExecutionHandler handler//可不設置)

在這裏插入圖片描述

  • core線程還能應付的,則不斷的創建新的線程,但不會超出corePoolSize;
  • core線程無法應付,則將任務扔到隊列裏面,並且用core線程去執行;
  • 工作隊列滿了(意味着插入任務失敗),則開始創建MAX線程,線程數達到MAX後,隊列還一直是滿的,則拋出RejectedExecutionException。

2.1、corePoolSize

核心線程池大小,當線程池中的線程數目小於corePoolSize時,新提交任務將創建一個新線程執行任務,即使此時線程池中存在空閒線程。

2.1、maximumPoolSize

最大線程池大小,表示當前池中可以活躍的最大線程數目。

2.3、keepAliveTime

線程池中超過corePoolSize數目的空閒線程最大存活時間。

2.4、TimeUnit

keepAliveTime時間單位。可以設置爲TimeUnit.MICROSECONDSTimeUnit.SECONDS等單位,分別表示毫秒和秒。

2.5、workQueue

阻塞任務隊列,用以存儲超出了corePoolSize的線程。

2.6、threadFactory

新建線程工廠。如果沒有的話則使用系統默認的。

2.7、RejectedExecutionHandler

當提交任務數超過maxmumPoolSize與workQueue之和時,任務會交給RejectedExecutionHandler來處理。如果沒有的話則使用系統默認的。

三、使用自己構造的ThreadPoolExecutor

測試類:

public class ThreadPoolExecutorDemo {

    @Test
    public void testThreadPoolExecutor(){
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                10,
                1000,
                TimeUnit.MICROSECONDS,
                new ArrayBlockingQueue<Runnable>(3),
                new MyThreadFactory(),
                new MyRejectedExecutionHandler());
        for (int i = 0; i < 35; i++) {

            int count = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    //模擬耗時操作
                    for (int j = 0; j < 500000; j++) {
                        //..
                    }
                    System.out.println("這是第"+count+"個線程在執行任務----"+Thread.currentThread().getName());

                }
            });
        }

    }

}

自定義的線程工廠類:

public class MyThreadFactory implements ThreadFactory {
    //線程標識器
    private AtomicInteger count  =  new AtomicInteger(0);

    @Override
    public Thread newThread(Runnable r) {
        //標識器自增1
        count.incrementAndGet();
        Thread thread = new Thread(r, "自定義線程(" + count + ")");
        return thread;
    }
}

自定義的異常處理類:

public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        //對超出的線程任務進行處理
        System.out.println("已處理...");
    }
}

執行後發現,當循環過多時,需要同時活躍的線程大於5個之後,新產生的線程進入阻塞隊列中,當需要同時活躍的線程大於10個之後,新產生的線程將被自定義的MyRejectedExecutionHandler 處理。
在這裏插入圖片描述

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