JUC編程:線程池的使用

線程池

線程池的好處:

  1. 降低資源的消耗
  2. 提高響應的速度
  3. 方便管理。

線程複用、可以控制最大併發數、管理線程

三大創建方法

  • ExecutorService threadPool = Executors.newSingleThreadExecutor();// 單個線程
  • ExecutorService threadPool = Executors.newFixedThreadPool(10);// 創建一 個固定的線程池的大小
  • ExecutorService threadPool = Executors.newCachedThreadPool(); // 由執行的線程數決定大小。

具體過程:創建線程池對象—>執行---->關閉線程池

 try {
        for (int i = 1; i <= 10; i++) {
                // 使用了線程池之後,使用線程池來創建線程
                threadPool.execute(()->{
                //執行的線程任務
                    System.out.println(Thread.currentThread().getName());
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 線程池用完,程序結束,關閉線程池
            threadPool.shutdown();
        }

七大參數

一般開發中使用線程池最好不使用Executors去創建對象。如阿里巴巴開發手冊所說的:OOM(內存溢出)
在這裏插入圖片描述
所以應該使用ThreadPoolExecutor來創建線程池
查看源碼得到以下:

  • 當執行線程數大於核心線程鎖時,其它休眠的線程位置將會啓用,最多不超過最大線程數。
  • 當超過最大線程鎖的線程任務會在阻塞隊列中進行等待。
  • 當此時併發執行的線程任務超過了最大線程數+阻塞隊列長度時,拒絕策略起效。

拒絕策略有四種

  • new ThreadPoolExecutor.AbortPolicy() // 同時併發的線程數大於最大線程數+阻塞隊列長度時,不處理超過部分的線程任務,直接拋出異常。
  • new ThreadPoolExecutor.DiscardPolicy() //同時併發的線程數大於最大線程數+阻塞隊列長度時,直接丟掉超過部分的線程任務,不拋出異常。
  • new ThreadPoolExecutor.CallerRunsPolicy() // 同時併發的線程數大於最大線程數+阻塞隊列長度時,超過部分的線程任務迴歸main主線程執行。
  • new ThreadPoolExecutor.DiscardOldestPolicy() //阻塞隊列滿了,嘗試去和最先執行的線程發起競爭,也不會拋出異常!

源碼中的是這樣的:

public ThreadPoolExecutor(int corePoolSize, //核心線程數
                              int maximumPoolSize, //最大線程數。最多幾個線程併發。
                              long keepAliveTime, //當線程無任務時,幾秒後結束該線程
                              TimeUnit unit,//線程結束的時間單位
                              BlockingQueue<Runnable> workQueue,//阻塞隊列,限制等候線程數
                              ThreadFactory threadFactory,//線程工廠
                              RejectedExecutionHandler handler)//拒絕策略

舉個創建的例子:

ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                Runtime.getRuntime().availableProcessors(),
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());  //隊列滿了,嘗試去和最早的競爭,也不會拋出異常!

如何選擇線程池的大小

  1. IO 密集型 :判斷你程序中十分耗IO的線程,有n個,線程池就設置(2n)個

  2. CPU 密集型:一般電腦幾核,線程池就設置幾個線程,可以保持cpu的效率最高!可以利用Runtime.getRuntime().availableProcessors()獲取當前主機的核數。

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