1. 程式人生 > >Java併發程式設計(6)-ThreadPoolExecutor解讀(1)

Java併發程式設計(6)-ThreadPoolExecutor解讀(1)

文章目錄


更多關於Java併發程式設計的文章請點選這裡:Java併發程式設計實踐(0)-目錄頁


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

一、什麼是ThreadPoolExecutor

ThreadPoolExecutor位於java.util.concurrent併發包下,為一些Executor提供了基本的實現,在JDK1.5中由Executors中的工廠中的newCachedThreadPool

newFixedThreadPoolnewScheduledThreadExecutor方法所返回。但在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 處理。
在這裡插入圖片描述