ThreadPoolExecutor線程池優化模擬

測試代碼

public class rejectHandler {


    public static void main(String[] arg){
        Random random = new Random();
        Executor executor = new ThreadPoolExecutor(2,  // 線程池駐留線程數量
                6,                                     // 線程池最大線程數量
                1,                                     // 線程回收延時
                SECONDS,                               // 線程回收延時單位
                new LinkedBlockingQueue<Runnable>(10), // 大小爲10的緩衝區
                Executors.defaultThreadFactory(),      // 設置創建線程的工廠爲默認
                new selfdefinedRejectionPolicy());     // 重寫的任務拒絕策略
        while(true) {
            try {
            // 模擬任務線程
                ((ThreadPoolExecutor) executor).submit(() -> {
                    try {
                        System.out.println("-------------------------");
                        System.out.println("Blocking Queue Size: "+((ThreadPoolExecutor) executor).getQueue().size());
                        System.out.println("Number of Threads: "+((ThreadPoolExecutor) executor).getPoolSize());
//                        long sleep = Math.abs((long)random.nextInt()/1000000);
//                        Thread.sleep(sleep);
// System.out.println("Having slept for " + sleep + "miliseconds.");
                        Thread.sleep(3000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                Thread.sleep(500);
            }catch (InterruptedException e1){
                e1.printStackTrace();
        }
        }
    }
}

代碼中我們啓了一個自己的線程池,第一個係數是線程池中駐留的線程數,如果系統的任務存在沒有任務的較長期的空閒時間,建議設爲0以節省系統資源;如果系統中來任務較爲頻繁建議設置一定數量的駐留線程。線程池最大線程數量爲這系統的最大容量,當任務到來頻繁時,可能需要增加線程數量以容納更多的任務執行。但是,系統資源是有限的,爲了是系統不至於崩潰,建議設置一個最大值以防止某些極限場景摧毀整個系統。當任務數量超過系統承受能力時,多餘的任務會被壓入一個緩衝隊列,如果你的系統時不時會有像DDOS一樣的任務潮,建議使用鏈式隊列(鏈表動態擴容)並將這個隊列設置得長一些。當任務實在多得連緩衝隊列都放不下時,會啓動拒絕策略,Executor提供的拒絕策略有四種,最常用的是Abort(拋異常)和Discard(丟棄)策略,這裏我們爲了統計被丟棄的任務數量,重寫了拒絕策略。

public class selfdefinedRejectionPolicy implements RejectedExecutionHandler {

    int count = 0;

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e){
        count++;
        System.out.println(count + "tasks have been discarded!");
    }
}

將加載任務和處理任務的時間分別設置爲上面的時間(500ms加載一個任務,處理一個任務需要3s):
-------------------------
Blocking Queue Size: 9
Number of Threads: 5
37tasks have been discarded!
-------------------------
Blocking Queue Size: 9
Number of Threads: 5

-------------------------
Blocking Queue Size: 9
Number of Threads: 5
可以看到系統開啓了全部5個線程,隊列也基本佔滿。在3min中內丟棄了37個任務。這說明我們可能需要更大的線程容量了。

當然現實的情況肯定不是如此理想,可以使用真實的任務替換代碼中的sleep過程。

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