ThreadPool的原理理解

提示:這裏我只是聊聊自己的理解,相當於自己記個筆記而已,如果有誤,請指正。

背景:爲了更加深刻的理解Java,近期比較深入理解線程池。

線程池優勢:線程池做的工作主要是控制運行的線程數量,處理過程中將任務放入隊列然後字線程創建後啓動這些任務,如果數量超過了最大數量,超出數量的線程放到隊列中等候,當其它線程執行完畢,再從隊列中取出任務來執行。簡單來講就是:控制最大併發數,管理線程。

線程池好處:(1)降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗;(2)提高響應速度。當任務到達時,任務可以不需要等待線程創建就能立即執行;(3)提高線程的可管理。線程是稀缺資,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配,調優和監控。

關係圖如下:

創建實例的方式:

public class MyThreadPoolDemo {
    public static void main(String[] args) {
        //Thread_3menthod();
        //現實中 使用這個(自定義)
        System.out.println(Runtime.getRuntime().availableProcessors());
        ExecutorService threadPool = new ThreadPoolExecutor(2,
                5,
                2L,
                TimeUnit.SECONDS,new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i=0;i<9;i++){
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
    //這裏是內置的方法,一般情況我們不用他們
    private static void Thread_3menthod() {
        //一池5個工作線程,相當於一個銀行有5個受理窗口
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        //一池1個工作線程,相當於一個銀行有1個受理窗口
        ExecutorService threadPool2 = Executors.newSingleThreadExecutor();
        //一池n個工作線程,相當於一個銀行有n個受理窗口
        ExecutorService threadPool3 = Executors.newCachedThreadPool();
        try {
            for (int i=0;i<10;i++){

                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
                });
                //TimeUnit.SECONDS.sleep(1);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

線程池七大參數理解:

  • corePoolSize:線程池中的常駐核心線程數
  • maxNumPoolSize:線程池中最多能容納同時執行的最大線程數,此值必須大於等於1
  • keeAliveTime:多餘的空閒的線程的存活時間,當前池中線程數量超過corePoolSize時,空閒實際達到keepAliveTime時,多餘線程會被銷燬知道剩下的線程數爲corePoolSize爲止
  • unit:keeyAliveTime的單位
  • workQueue:任務隊列,被提到尚未執行的任務
  • threadFactory:表示生成線程池中工作線程的工廠,用於創建線程,一般用默認Executors.defaultThreadFactory()
    即可
  • handler:決絕策略,表示隊列慢了,並且工作線程大於等於maxNumPoolSize時如何在拒絕請求執行的runnable的策略(策略可選如下圖)

執行過程如下:

  1. 在創建了線程池後,開始等待請求;
  2. 當調用execute()方法添加一個請求任務是,線程池會做出如下判斷:(1)如果正在運行的線程數量小於corePoolSize時,那麼立馬創建線程運行這個任務(2)如果正在運行的線程數量大於或等於corePoolSize,那麼將這個任務放入隊列(3)如果這個時候隊列滿了且正在運行的線程數量還小於maxNumPoolSize,那麼還是要創建費核心線程立刻運行這個任務(4)如果隊列滿了且正在運行的線程數量大於等於maxNumPoolSize,那麼線程池會自動飽和拒絕策略來執行
  3. 當一個線程完成任務時,它會從隊列中取下一個任務來執行
  4. 當一個線程無事可做超過keepAliveTime時,線程會判斷,如果當前運行的線程數大於corePoolSize時,那麼這個線程會被停掉

實際中選哪個使用:

根據阿里開發的手冊,線程池不允許使用Executors去創建的,而是通過ThreadExecutor的方式創建。原因:Executors返回的線程池弊端如下:(1)Executors.newFixedThreadPool、Executors.newSingleThreadExecutor、Executors.newScheduledThreadPool和Executors.newCachedThreadPool(),允許的請求隊列長度長度Integer.MAX_VALUE,可能會堆積大量的請求,從而導致OOM。

現總結到這吧!!

 

 

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