中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

線程池的實現原理是什么

發布時間:2021-06-21 18:22:51 來源:億速云 閱讀:149 作者:Leah 欄目:大數據

這篇文章給大家介紹線程池的實現原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

為什么要用線程池

線程是不是越多好?

  • 線程在Java中是一個對象, 更是操作系統的資源, 線程額創建和銷毀都需要時間,如果 創建時間+銷毀時間>執行任務時間 就很不合算

  • Java對象占用堆內存,操作系統線程占用系統內存, 根據JVM規范,一個線程默認最大棧大小為1M, 這個棧空間是要從操作系統內存中分配的,線程過多會消耗很多的內存

  • 操作系統頻繁切換線程上下文會影響性能

線程池的推出就是為了控制線程數量

線程池原理 - 概念

  • 線程池管理器:

    用于創建并管理線程池, 包括創建線程池, 銷毀線程池, 添加新任務

  • 工作線程:

    線程池中的線程, 在沒有任務時處于等待狀態, 可以循環的執行任務

  • 任務接口:

    每個任務必須實現的接口,以供工作線程任務調度的執行, 它主要規定了任務的入口,任務執行完后的收尾工作,任務的執行狀態等

  • 任務隊列:

    用于存放沒有處理的任務,提供一種緩沖

線程池的實現原理是什么

線程池API - 接口定義和實現類

線程池的實現原理是什么

線程池API - 方法定義

ExecutorService

線程池的實現原理是什么

cheduledExecutorService

線程池的實現原理是什么

線程池API - Executors工具類

可以自己實例化線程池, 也可以用Executors創建線程池,方法如下:

  • newFixedThreadPool(int nThreads) : 創建一個固定大小,任務隊列無界的的線程池,核心線程數=最大線程數

  • newCachedThreadPool() : 創建一個大小無界的緩沖線程池,它的任務隊列是一個同步隊列,任務加入加入到池中,如果池中有空閑線程, 則用空閑線程執行,如無則創建新線程執行,池中的空閑線程超過60秒, 將被銷毀釋放, 線程數隨任務的多少變化,適用于耗時較小的異步任務, 池的核心線程數=0, 最大線程數=Integer.MAX_VALUE

  • newSingleThreadExecutor() : 只有一個線程來執行無界任務隊列的單一線程池,該線程池確保任務按加入的順序一個一個的依次執行,當唯一的線程因任務異常中止時,將創建一個新的線程來繼續執行后續的任務, 與newFixedThreadPool(1)的區別在于,單一線程池的池大小在newSingleThreadExecutor方法中硬編碼,不能再改變

  • newScheduledThreadPool(int corePoolSize) : 能定時執行任務的線程池,該池的核心線程數由參數指定,最大線程數=Integer.MAX_VALUE

線程池原理 - 任務執行過程

  1. 是否達到核心線程數量?

    沒達到,創建一個工作線程來執行任務

  2. 工作隊列是否已滿?

    沒滿,則將新提交的任務存儲在任務隊列中

  3. 是否達到線程池最大數量?

    則創建一個新的線程來執行任務

  4. 最后,執行拒絕策略來處理這個任務

線程池的實現原理是什么  

代碼示例:

package com.neteasy.demo;

import java.util.List;
import java.util.concurrent.*;

/** 線程池的使用 */
public class Demo7 {

 /**
  * 測試:提交15個執行時間需要3秒的任務,看線程池的狀況
  *
  * @param threadPoolExecutor
  * @throws Exception
  */
 private void testCommon(ThreadPoolExecutor threadPoolExecutor) throws Exception {
   // 測試:提交15個執行時間需要3秒的任務,看超過大小的2個,對應的處理情況
   for (int i = 0; i < 15; i++) {
     int n = i;
     threadPoolExecutor.submit(
         new Runnable() {
           @Override
           public void run() {
             try {
               System.out.println("開始執行:" + n);
               Thread.sleep(3000L);
               System.out.println("執行結束:" + n);
             } catch (InterruptedException e) {
               e.printStackTrace();
             }
           }
         });
     System.out.println("任務提交成功:" + i);
   }
   // 查看線程數量,查看隊列等待數量
   Thread.sleep(500L);
   System.out.println("當前線程池線程數量為:" + threadPoolExecutor.getPoolSize());
   System.out.println("當前線程池等待的數量為" + threadPoolExecutor.getQueue().size());
   // 等待15秒,查看線程數量和隊列數量(理論上,會被超出核心線程數量的線程自動銷毀)
   Thread.sleep(15000L);
   System.out.println("當前線程池線程數量為:" + threadPoolExecutor.getPoolSize());
   System.out.println("當前線程池等待的數量為:" + threadPoolExecutor.getQueue().size());
 }

 /**
  * 1、線程池信息:核心線程數量5,最大數量10,無界隊列,超出核心線程數量的線程存活時間:5秒, 指定拒絕策略的
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest1() throws Exception {
   ThreadPoolExecutor threadPoolExecutor =
       new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
   testCommon(threadPoolExecutor);
   // 預計結果:線程池線程數量為:5,超出數量的任務,其他的進入隊列中等待被執行
 }

 /**
  * 2、 線程池信息:核心線程數量5,最大數量10,隊列大小3,超出核心線程數量的線程存活時間:5秒, 指定拒絕策略的
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest2() throws Exception {
   // 創建一個 核心線程數量為5,最大數量為10,等待隊列最大是3 的線程池,也就是最大容納13個任務。
   // 默認的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
   ThreadPoolExecutor threadPoolExecutor =
       new ThreadPoolExecutor(
           5,
           10,
           5,
           TimeUnit.SECONDS,
           new LinkedBlockingDeque<Runnable>(3),
           new RejectedExecutionHandler() {
             @Override
             public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
               System.err.println("有任務被拒絕執行了");
             }
           });
   testCommon(threadPoolExecutor);
   // 預計結果:
   // 1、 5個任務直接分配線程開始執行
   // 2、 3個任務進入等待隊列
   // 3、 隊列不夠用,臨時加開5個線程來執行任務(5秒沒活干就銷毀)
   // 4、 隊列和線程池都滿了,剩下2個任務,沒資源了,被拒絕執行。
   // 5、 任務執行,5秒后,如果無任務可執行,銷毀臨時創建的5個線程
 }

 /**
  * 3、 線程池信息:核心線程數量5,最大數量5,無界隊列,超出核心線程數量的線程存活時間:5秒
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest3() throws Exception {
   // 和Executors.newFixedThreadPool(int nThreads)一樣的
   ThreadPoolExecutor threadPoolExecutor =
       new ThreadPoolExecutor(
           5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
   testCommon(threadPoolExecutor);
   // 預計結:線程池線程數量為:5,超出數量的任務,其他的進入隊列中等待被執行
 }

 /**
  * 4、 線程池信息:核心線程數量0,最大數量Integer.MAX_VALUE,SynchronousQueue隊列,超出核心線程數量的線程存活時間:60秒
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest4() throws Exception {

   /**
    * SynchronousQueue,實際上它不是一個真正的隊列,因為它不會為隊列中元素維護存儲空間。與其他隊列不同的是,它維護一組線程,這些線程在等待著把元素加入或移出隊列。
    * 在使用SynchronousQueue作為工作隊列的前提下,客戶端代碼向線程池提交任務時, 而線程池中又沒有空閑的線程能夠從SynchronousQueue隊列實例中取一個任務,
    * 那么相應的offer方法調用就會失敗(即任務沒有被存入工作隊列)。此時,ThreadPoolExecutor會新建一個新的工作者線程用于對這個入隊列失敗的任務進行處理
    * (假設此時線程池的大小還未達到其最大線程池大小maximumPoolSize)。
    */
   // 和Executors.newCachedThreadPool()一樣的
   ThreadPoolExecutor threadPoolExecutor =
       new ThreadPoolExecutor(
           0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
   testCommon(threadPoolExecutor);
   // 預計結果:
   // 1、 線程池線程數量為:15,超出數量的任務,其他的進入隊列中等待被執行
   // 2、 所有任務執行結束,60秒后,如果無任務可執行,所有線程全部被銷毀,池的大小恢復為0
   Thread.sleep(60000L);
   System.out.println("60秒后,再看線程池中的數量:" + threadPoolExecutor.getPoolSize());
 }

 /**
  * 5、 定時執行線程池信息:3秒后執行,一次性任務,到點就執行
  * 核心線程數量5,最大數量Integer.MAX_VALUE,DelayedWorkQueue延時隊列,超出核心線程數量的線程存活時間:0秒
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest5() throws Exception {
   // 和Executors.newScheduledThreadPool()一樣的
   ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(5);
   threadPoolExecutor.schedule(
       new Runnable() {
         @Override
         public void run() {
           System.out.println("任務被執行,現在時間:" + System.currentTimeMillis());
         }
       },
       3000,
       TimeUnit.MILLISECONDS);
   System.out.println(
       "定時任務,提交成功,時間是:"
           + System.currentTimeMillis()
           + ", 當前線程池中線程數量:"
           + threadPoolExecutor.getPoolSize());
   // 預計結果:任務在3秒后被執行一次
 }

 /**
  * 6、 定時執行線程池信息:線程固定數量5 ,<br>
  * 核心線程數量5,最大數量Integer.MAX_VALUE,DelayedWorkQueue延時隊列,超出核心線程數量的線程存活時間:0秒
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest6() throws Exception {
   ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(5);
   /**
    * 周期性執行某一個任務,線程池提供了兩種調度方式,這里單獨演示一下。測試場景一樣。測試場景:提交的任務需要3秒才能執行完畢。看兩種不同調度方式的區別 效果1:
    * 提交后,2秒后開始第一次執行,之后每間隔1秒,固定執行一次(如果發現上次執行還未完畢,則等待完畢,完畢后立刻執行)。
    * 也就是說這個代碼中是,3秒鐘執行一次(計算方式:每次執行三秒,間隔時間1秒,執行結束后馬上開始下一次執行,無需等待)
    */
   threadPoolExecutor.scheduleAtFixedRate(
       new Runnable() {
         @Override
         public void run() {
           try {
             Thread.sleep(3000L);
           } catch (InterruptedException e) {
             e.printStackTrace();
           }
           System.out.println("任務-1 被執行,現在時間:" + System.currentTimeMillis());
         }
       },
       2000,
       1000,
       TimeUnit.MILLISECONDS);

   /**
    * 效果2:提交后,2秒后開始第一次執行,之后每間隔1秒,固定執行一次(如果發現上次執行還未完畢,則等待完畢,等上一次執行完畢后再開始計時,等待1秒)。
    * 也就是說這個代碼鐘的效果看到的是:4秒執行一次。(計算方式:每次執行3秒,間隔時間1秒,執行完以后再等待1秒,所以是 3+1)
    */
   threadPoolExecutor.scheduleWithFixedDelay(
       new Runnable() {
         @Override
         public void run() {
           try {
             Thread.sleep(3000L);
           } catch (InterruptedException e) {
             e.printStackTrace();
           }
           System.out.println("任務-2 被執行,現在時間:" + System.currentTimeMillis());
         }
       },
       2000,
       1000,
       TimeUnit.MILLISECONDS);
 }

 private ThreadPoolExecutor testShutdownCommon() {
   // 創建一個 核心線程數量為5,最大數量為10,等待隊列最大是3的線程池,也就是最大容納13個任務。
   // 默認的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
   ThreadPoolExecutor threadPoolExecutor =
       new ThreadPoolExecutor(
           5,
           10,
           5,
           TimeUnit.SECONDS,
           new LinkedBlockingQueue<Runnable>(3),
           new RejectedExecutionHandler() {
             @Override
             public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
               System.err.println("有任務被拒絕執行了");
             }
           });
   // 測試:提交15個執行時間需要3秒的任務,看超過大小的2個,對應的處理情況
   for (int i = 0; i < 15; i++) {
     int n = i;
     threadPoolExecutor.submit(
         new Runnable() {
           @Override
           public void run() {
             try {
               System.out.println("開始執行:" + n);
               Thread.sleep(3000L);
               System.err.println("執行結束:" + n);
             } catch (InterruptedException e) {
               System.out.println("異常:" + e.getMessage());
             }
           }
         });
     System.out.println("任務提交成功 :" + i);
   }
   return threadPoolExecutor;
 }

 /**
  * 7、 終止線程:線程池信息:核心線程數量5,最大數量10,隊列大小3,超出核心線程數量的線程存活時間:5秒, 指定拒絕策略的
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest7() throws Exception {
   ThreadPoolExecutor threadPoolExecutor = testShutdownCommon();
   // 1秒后終止線程池
   Thread.sleep(1000L);
   threadPoolExecutor.shutdown();
   // 再次提交提示失敗
   threadPoolExecutor.submit(
       new Runnable() {
         @Override
         public void run() {
           System.out.println("追加一個任務");
         }
       });
   // 結果分析
   // 1、 10個任務被執行,3個任務進入隊列等待,2個任務被拒絕執行
   // 2、調用shutdown后,不接收新的任務,等待13任務執行結束
   // 3、 追加的任務在線程池關閉后,無法再提交,會被拒絕執行
 }

 /**
  * 8、 立刻終止線程:線程池信息:核心線程數量5,最大數量10,隊列大小3,超出核心線程數量的線程存活時間:5秒, 指定拒絕策略的
  *
  * @throws Exception
  */
 private void threadPoolExecutorTest8() throws Exception {
   // 創建一個 核心線程數量為5,最大數量為10,等待隊列最大是3 的線程池,也就是最大容納13個任務。
   // 默認的策略是拋出RejectedExecutionException異常,java.util.concurrent.ThreadPoolExecutor.AbortPolicy
   ThreadPoolExecutor threadPoolExecutor = testShutdownCommon();
   // 1秒后終止線程池
   Thread.sleep(1000L);
   List<Runnable> shutdownNow = threadPoolExecutor.shutdownNow();
   // 再次提交提示失敗
   threadPoolExecutor.submit(
       new Runnable() {
         @Override
         public void run() {
           System.out.println("追加一個任務");
         }
       });
   System.out.println("未結束的任務有:" + shutdownNow.size());

   // 結果分析
   // 1、 10個任務被執行,3個任務進入隊列等待,2個任務被拒絕執行
   // 2、調用shutdownnow后,隊列中的3個線程不再執行,10個線程被終止
   // 3、 追加的任務在線程池關閉后,無法再提交,會被拒絕執行
 }

 public static void main(String[] args) throws Exception {
   Demo7 demo7 = new Demo7();
   //    demo7.threadPoolExecutorTest1();
   //    demo7.threadPoolExecutorTest2();
   //    demo7.threadPoolExecutorTest3();
   //    demo7.threadPoolExecutorTest4();
   //    demo7.threadPoolExecutorTest5();
   //    demo7.threadPoolExecutorTest6();
   //    demo7.threadPoolExecutorTest7();
   demo7.threadPoolExecutorTest8();
 }
}

關于線程池的實現原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

遂昌县| 汾西县| 磴口县| 英德市| 墨江| 满城县| 伊金霍洛旗| 都匀市| 临湘市| 志丹县| 贡嘎县| 绥棱县| 沂源县| 瓦房店市| 盖州市| 盐亭县| 林州市| 开原市| 大理市| 阿巴嘎旗| 达州市| 四平市| 郎溪县| 宁乡县| 宜宾市| 丰都县| 咸宁市| 宣恩县| 达拉特旗| 文水县| 黔西县| 应城市| 通化市| 治多县| 肥城市| 商河县| 繁峙县| 武宣县| 漳平市| 德安县| 宁强县|