最近一段時間,咱們一直都在分享多線程相關知識,也一直有用線程池,可是一直沒有介紹線程池相關知識,因此今天咱們就先來看下線程池相關的知識點。緩存
ThreadPool,線程池,顧名思義就是存放線程的池子,也是jdk1.5引入的。對咱們而言,它的最主要優點就是簡化了線程啓動流程,讓咱們能夠更方便地使用多線程,不再用手動start線程,直接經過線程池提交咱們的任務便可,並且合理使用線程池至於能夠帶來如下幾個好處:多線程
下降資源消耗:複用線程,下降建立和銷燬線程帶來的資源消耗ide
提升響應速度:使用線程池,省去了線程建立和初始化過程,因此任務能夠更快執行線程
提升線程的可管理性:能夠直接經過線程池管理、監控、調度線程,線程管理更方便debug
經常使用的線程池有SingleThreadExecutor、CachedThreadPool、ScheduledThreadPool、FixedThreadPool,他們分別是單線程調度器,緩存線程池,定時任務線程池和固定線程池,他們均可以經過Executors建立,調用對應的靜態方法便可,因爲這一塊的內容比較多,因此今天就簡單提一下,後面專門講一次。3d
咱們今天着重講下自定義線程池,自定義線程池也很簡單,直接new ThreadPoolExecutor() ,而後傳入對應的參數便可,你們能夠看下下面的示例:blog
int corePoolSize = 10; int maximumPoolSize = 20; long keepAliveTime = 1000; TimeUnit unit = TimeUnit.MICROSECONDS; BlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); for (int i = 0; i < 50; i++) { threadPoolExecutor.execute(() -> { String name = Thread.currentThread().getName(); System.out.println("hello threadPool: "+ name); }); } threadPoolExecutor.shutdown();
ThreadPoolExecutor有三個構造方法,至少須要三個參數隊列
其中第一個參數是線程池的基本大小,當你提交一個任務到線程池時,線程池會建立一個線程來執行任務,即便又空閒的線程存在,線程池依然會啓動一個新線程來執行當前任務,直到線程池中的線程數達到線程基本大小(corePoolSize);資源
第二個參數是線程池容許建立的最大線程數。若是工做隊列(第三個參數)滿了,且建立線程數已達到線程池基本大小,則線程池會繼續建立新的線程來執行任務。若是你指定的工做隊列是***的,那這個參數也就失效了。get
第三個參數就是線程池工做隊列,就是當你須要執行的任務超過線程池基本大小的時候,會把超出部分放進工做隊列,等待線程池基本線程資源釋放。
下面咱們分別驗證以上三點,運行上面的示例代碼:
在第一次循環的時候(i=0),咱們發現線程池的size是0,活動線程數也是0,任務隊列也是0,完成任務數也是0,這也說明線程池在最開始的時候是沒有建立線程的;
而後咱們讓他循環到第9次(i=8),這時候線程池已經被初始化,有8個線程(因爲斷點的緣由,第9個線程還沒有被建立),活動線程數5,完成執行的任務數3,任務隊列仍是0,說明確實在未達到線程池基本大小時,會不斷建立新的線程;
咱們繼續執行,讓他循環到第15次(i=14),可結果彷佛和咱們預期不同,按照預期,線程池的size應該是10,活動線程數也是10,任務隊列也是4,完成任務數可能不肯定,因此這裏確定不能經過debug的方式來看了,由於debug停頓以後好多線程資源已經被釋放,任務根本就不會堆積,因此任務隊列就不會有數據:
因此這裏我在線程池啓動任務前加一行打印,打印線程池數據
而後在運行,就能夠拿到運行數據:
這樣的數據纔是真實的,由於實際運行的時候,線程啓動是很是快的,因此執行完成的任務數應該是0,等待任務數是4。
咱們前面設定的最大線程數是20,可是翻看運行記錄,我發現線程池的大小始終是10,說明只要不打到任務隊列的上限,並不會建立新的線程,這裏咱們把循環次數改成60,而後運行下:
可是依然沒有建立新的線程,由於仍是內沒有達到任務隊列上限,咱們把循環次數再調大一點,調到70:
如今線程池的大小就變成了19,活動線程數19,可是這時候若是你繼續調大循環次數,線程池就會報錯了:
這個錯誤的緣由就是線程池資源已經耗盡了,沒法再接收新的任務了,這也就是說線程池可以處理的最大任務數是corePoolSize + maximumPoolSize + workQueue.size() ,固然,若是你的workQueue不設定大小,那永遠都不會報這個錯誤,固然maximumPoolSize 也就無效了。
本來打算線程池一次分享完的,可是實際分享過程當中發現內容太多了(已經一千五百字了),因此今天就先到這裏,明天再繼續分享線程池其餘內容。總的來講,今天的內容已經說明白了線程池不少基礎的知識點(反正我本身以爲我都有好多收穫),算是乾貨滿滿吧,你若是掌握了這些知識點,至少在使用線程池的過程當中會少踩好多坑。好了,今天就先說這麼多吧!