深入理解 Java 線程池,講解的太清晰了

2020-12-13 Java編程技術樂園

及時獲取有趣有料的技術文章

做一個積極的人編碼、改bug、提升自己

我有一個樂園,面向編程,春暖花開!

一、簡介

什麼是線程池

線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然後在創建線程後自動啟動這些任務。

為什麼要用線程池

如果並發請求數量很多,但每個線程執行的時間很短,就會出現頻繁的創建和銷毀線程。如此一來,會大大降低系統的效率,可能頻繁創建和銷毀線程的時間、資源開銷要大於實際工作的所需。

正是由於這個問題,所以有必要引入線程池。使用 線程池的好處有以下幾點:

降低資源消耗 - 通過重複利用已創建的線程降低線程創建和銷毀造成的消耗。提高響應速度 - 當任務到達時,任務可以不需要等到線程創建就能立即執行。提高線程的可管理性 - 線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。但是要做到合理的利用線程池,必須對其原理了如指掌。二、Executor 框架

Executor 框架是一個根據一組執行策略調用,調度,執行和控制的異步任務的框架,目的是提供一種將」任務提交」與」任務如何運行」分離開來的機制。

核心 API 概述

Executor 框架核心 API 如下:

Executor - 運行任務的簡單接口。ExecutorService - 擴展了 Executor 接口。擴展能力:支持有返回值的線程;支持管理線程的生命周期。ScheduledExecutorService - 擴展了 ExecutorService 接口。擴展能力:支持定期執行任務。AbstractExecutorService - ExecutorService 接口的默認實現。ThreadPoolExecutor - Executor 框架最核心的類,它繼承了 AbstractExecutorService 類。ScheduledThreadPoolExecutor - ScheduledExecutorService 接口的實現,一個可定時調度任務的線程池。Executors - 可以通過調用 Executors 的靜態工廠方法來創建線程池並返回一個 ExecutorService 對象。

Executor

Executor 接口中只定義了一個 execute 方法,用於接收一個 Runnable 對象。

publicinterfaceExecutor{voidexecute(Runnable command);}ExecutorService

ExecutorService 接口繼承了 Executor 接口,它還提供了 invokeAll、invokeAny、shutdown、submit 等方法。

publicinterfaceExecutorServiceextendsExecutor{voidshutdown();List<Runnable> shutdownNow();booleanisShutdown();booleanisTerminated();booleanawaitTermination(long timeout, TimeUnit unit)throws InterruptedException; <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); Future<?> submit(Runnable task); <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)throws InterruptedException; <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException; <T> T invokeAny(Collection<? extends Callable<T>> tasks)throws InterruptedException, ExecutionException; <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;}從其支持的方法定義,不難看出:相比於 Executor 接口,ExecutorService 接口主要的擴展是:

支持有返回值的線程 - sumbit、invokeAll、invokeAny 方法中都支持傳入Callable 對象。支持管理線程生命周期 - shutdown、shutdownNow、isShutdown 等方法。ScheduledExecutorService

ScheduledExecutorService 接口擴展了 ExecutorService 接口。

它除了支持前面兩個接口的所有能力以外,還支持定時調度線程。

publicinterfaceScheduledExecutorServiceextendsExecutorService{public ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit);public <V> ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period, TimeUnit unit);public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay, TimeUnit unit);}其擴展的接口提供以下能力:

schedule 方法可以在指定的延時後執行一個 Runnable 或者 Callable 任務。scheduleAtFixedRate 方法和 scheduleWithFixedDelay 方法可以按照指定時間間隔,定期執行任務。三、ThreadPoolExecutor

java.uitl.concurrent.ThreadPoolExecutor 類是 Executor 框架中最核心的類。所以,本文將著重講述一下這個類。

重要欄位

ThreadPoolExecutor 有以下重要欄位:

privatefinal AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));privatestaticfinalint COUNT_BITS = Integer.SIZE - 3;privatestaticfinalint CAPACITY = (1 << COUNT_BITS) - 1;// runState is stored in the high-order bitsprivatestaticfinalint RUNNING = -1 << COUNT_BITS;privatestaticfinalint SHUTDOWN = 0 << COUNT_BITS;privatestaticfinalint STOP = 1 << COUNT_BITS;privatestaticfinalint TIDYING = 2 << COUNT_BITS;privatestaticfinalint TERMINATED = 3 << COUNT_BITS;參數說明:

ctl - 用於控制線程池的運行狀態和線程池中的有效線程數量。它包含兩部分的信息:線程池的運行狀態 (runState)線程池內有效線程的數量 (workerCount)可以看到,ctl 使用了 Integer 類型來保存,高 3 位保存 runState,低 29 位保存 workerCount。COUNT_BITS 就是 29,CAPACITY 就是 1 左移 29 位減 1(29 個 1),這個常量表示 workerCount 的上限值,大約是 5 億。運行狀態 - 線程池一共有五種運行狀態:線程池不是 RUNNING 狀態;線程池狀態不是 TIDYING 狀態或 TERMINATED 狀態;如果線程池狀態是 SHUTDOWN 並且 workerQueue 為空;workerCount 為 0;設置 TIDYING 狀態成功。在線程池處於 RUNNING 狀態時,調用 shutdown 方法會使線程池進入到該狀態。finalize 方法在執行過程中也會調用 shutdown 方法進入該狀態。RUNNING - 運行狀態。接受新任務,並且也能處理阻塞隊列中的任務。SHUTDOWN - 關閉狀態。不接受新任務,但可以處理阻塞隊列中的任務。STOP - 停止狀態。不接受新任務,也不處理隊列中的任務。會中斷正在處理任務的線程。在線程池處於 RUNNING 或 SHUTDOWN 狀態時,調用 shutdownNow 方法會使線程池進入到該狀態。TIDYING - 整理狀態。如果所有的任務都已終止了,workerCount (有效線程數) 為 0,線程池進入該狀態後會調用 terminated 方法進入 TERMINATED 狀態。TERMINATED - 已終止狀態。在 terminated 方法執行完後進入該狀態。默認 terminated 方法中什麼也沒有做。進入 TERMINATED 的條件如下:

構造方法

ThreadPoolExecutor 有四個構造方法,前三個都是基於第四個實現。第四個構造方法定義如下:

publicThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler){參數說明:

corePoolSize - 核心線程數量。當有新任務通過 execute 方法提交時 ,線程池會執行以下判斷:如果運行的線程數少於 corePoolSize,則創建新線程來處理任務,即使線程池中的其他線程是空閒的。如果線程池中的線程數量大於等於 corePoolSize 且小於 maximumPoolSize,則只有當 workQueue 滿時才創建新的線程去處理任務;如果設置的 corePoolSize 和 maximumPoolSize 相同,則創建的線程池的大小是固定的。這時如果有新任務提交,若 workQueue 未滿,則將請求放入 workQueue 中,等待有空閒的線程去從 workQueue 中取任務並處理;如果運行的線程數量大於等於 maximumPoolSize,這時如果 workQueue 已經滿了,則使用 handler 所指定的策略來處理任務;所以,任務提交時,判斷的順序為 corePoolSize => workQueue => maximumPoolSize。maximumPoolSize - 最大線程數量如果隊列滿了,並且已創建的線程數小於最大線程數,則線程池會再創建新的線程執行任務。值得注意的是:如果使用了無界的任務隊列這個參數就沒什麼效果。keepAliveTime:線程保持活動的時間當線程池中的線程數量大於 corePoolSize 的時候,如果這時沒有新的任務提交,核心線程外的線程不會立即銷毀,而是會等待,直到等待的時間超過了 keepAliveTime。所以,如果任務很多,並且每個任務執行的時間比較短,可以調大這個時間,提高線程的利用率。unit - keepAliveTime 的時間單位。有 7 種取值。可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。workQueue - 等待執行的任務隊列。用於保存等待執行的任務的阻塞隊列。可以選擇以下幾個阻塞隊列。每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處於阻塞狀態。吞吐量通常要高於 LinkedBlockingQueue。Executors.newCachedThreadPool 使用了這個隊列。此隊列是基於鍊表的先進先出隊列(FIFO)如果創建時沒有指定此隊列大小,則默認為 Integer.MAX_VALUE。吞吐量通常要高於 ArrayBlockingQueue。使用 LinkedBlockingQueue 意味著: maximumPoolSize 將不起作用,線程池能創建的最大線程數為 corePoolSize,因為任務等待隊列是無界隊列。Executors.newFixedThreadPool 使用了這個隊列。此隊列是基於數組的先進先出隊列(FIFO)此隊列創建時必須指定大小。ArrayBlockingQueue - 有界阻塞隊列LinkedBlockingQueue - 無界阻塞隊列SynchronousQueue - 不會保存提交的任務,而是將直接新建一個線程來執行新來的任務PriorityBlockingQueue - 具有優先級的無界阻塞隊列threadFactory - 線程工廠。可以通過線程工廠給每個創建出來的線程設置更有意義的名字。handler - 飽和策略。它是 RejectedExecutionHandler 類型的變量。當隊列和線程池都滿了,說明線程池處於飽和狀態,那麼必須採取一種策略處理提交的新任務。線程池支持以下策略:AbortPolicy - 丟棄任務並拋出異常。這也是默認策略。DiscardPolicy - 丟棄任務,但不拋出異常。DiscardOldestPolicy - 丟棄隊列最前面的任務,然後重新嘗試執行任務(重複此過程)。CallerRunsPolicy - 只用調用者所在的線程來運行任務。如果以上策略都不能滿足需要,也可以通過實現 RejectedExecutionHandler 接口來定製處理策略。如記錄日誌或持久化不能處理的任務。execute 方法

默認情況下,創建線程池之後,線程池中是沒有線程的,需要提交任務之後才會創建線程。

提交任務可以使用 execute 方法,它是 ThreadPoolExecutor 的核心方法,通過這個方法可以向線程池提交一個任務,交由線程池去執行

execute 方法工作流程如下:

如果 workerCount < corePoolSize,則創建並啟動一個線程來執行新提交的任務;如果 workerCount >= corePoolSize,且線程池內的阻塞隊列未滿,則將任務添加到該阻塞隊列中;如果 workerCount >= corePoolSize && workerCount < maximumPoolSize,且線程池內的阻塞隊列已滿,則創建並啟動一個線程來執行新提交的任務;如果workerCount >= maximumPoolSize,並且線程池內的阻塞隊列已滿,則根據拒絕策略來處理該任務, 默認的處理方式是直接拋異常。

其他重要方法

在 ThreadPoolExecutor 類中還有一些重要的方法:

submit - 類似於 execute,但是針對的是有返回值的線程。submit 方法是在 ExecutorService 中聲明的方法,在 AbstractExecutorService 就已經有了具體的實現。ThreadPoolExecutor 直接復用 AbstractExecutorService 的 submit 方法。shutdown - 不會立即終止線程池,而是要等所有任務緩存隊列中的任務都執行完後才終止,但再也不會接受新的任務。將線程池切換到 SHUTDOWN 狀態;並調用 interruptIdleWorkers 方法請求中斷所有空閒的 worker;最後調用 tryTerminate 嘗試結束線程池。shutdownNow - 立即終止線程池,並嘗試打斷正在執行的任務,並且清空任務緩存隊列,返回尚未執行的任務。與 shutdown 方法類似,不同的地方在於:設置狀態為 STOP;中斷所有工作線程,無論是否是空閒的;取出阻塞隊列中沒有被執行的任務並返回。isShutdown - 調用了 shutdown 或 shutdownNow 方法後,isShutdown 方法就會返回 true。isTerminaed - 當所有的任務都已關閉後,才表示線程池關閉成功,這時調用 isTerminaed 方法會返回 true。setCorePoolSize - 設置核心線程數大小。setMaximumPoolSize - 設置最大線程數大小。getTaskCount - 線程池已經執行的和未執行的任務總數;getCompletedTaskCount - 線程池已完成的任務數量,該值小於等於 taskCount;getLargestPoolSize - 線程池曾經創建過的最大線程數量。通過這個數據可以知道線程池是否滿過,也就是達到了 maximumPoolSize;getPoolSize - 線程池當前的線程數量;getActiveCount - 當前線程池中正在執行任務的線程數量。使用示例

publicclassThreadPoolExecutorDemo{publicstaticvoidmain(String[] args){ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 100; i++) { threadPoolExecutor.execute(new MyThread()); String info = String.format("線程池中線程數目:%s,隊列中等待執行的任務數目:%s,已執行玩別的任務數目:%s", threadPoolExecutor.getPoolSize(), threadPoolExecutor.getQueue().size(), threadPoolExecutor.getCompletedTaskCount()); System.out.println(info); } threadPoolExecutor.shutdown(); }staticclassMyThreadimplementsRunnable{@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }}四、Executors

JDK 的 Executors 類中提供了幾種具有代表性的線程池,這些線程池 都是基於 ThreadPoolExecutor 的定製化實現

在實際使用線程池的場景中,我們往往不是直接使用 ThreadPoolExecutor ,而是使用 JDK 中提供的具有代表性的線程池實例。

newSingleThreadExecutor

創建一個單線程的線程池

只會創建唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。 如果這個唯一的線程因為異常結束,那麼會有一個新的線程來替代它

單工作線程最大的特點是:可保證順序地執行各個任務

示例:

publicclassSingleThreadExecutorDemo{publicstaticvoidmain(String[] args){ ExecutorService executorService = Executors.newSingleThreadExecutor();for (int i = 0; i < 100; i++) { executorService.execute(new Runnable() {@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }); } executorService.shutdown(); }}newFixedThreadPool

創建一個固定大小的線程池

每次提交一個任務就會新創建一個工作線程,如果工作線程數量達到線程池最大線程數,則將提交的任務存入到阻塞隊列中

FixedThreadPool 是一個典型且優秀的線程池,它具有線程池提高程序效率和節省創建線程時所耗的開銷的優點。但是,在線程池空閒時,即線程池中沒有可運行任務時,它不會釋放工作線程,還會佔用一定的系統資源。

示例:

publicclassFixedThreadPoolDemo{publicstaticvoidmain(String[] args){ ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 100; i++) { executorService.execute(new Runnable() {@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }); } executorService.shutdown(); }}newCachedThreadPool

創建一個可緩存的線程池

如果線程池長度超過處理任務所需要的線程數,就會回收部分空閒的線程;如果長時間沒有往線程池中提交任務,即如果工作線程空閒了指定的時間(默認為 1 分鐘),則該工作線程將自動終止。終止後,如果你又提交了新的任務,則線程池重新創建一個工作線程。此線程池不會對線程池大小做限制,線程池大小完全依賴於作業系統(或者說 JVM)能夠創建的最大線程大小。因此,使用 CachedThreadPool 時,一定要注意控制任務的數量,否則,由於大量線程同時運行,很有會造成系統癱瘓。示例:

publicclassCachedThreadPoolDemo{publicstaticvoidmain(String[] args){ ExecutorService executorService = Executors.newCachedThreadPool();for (int i = 0; i < 100; i++) { executorService.execute(new Runnable() {@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }); } executorService.shutdown(); }}newScheduleThreadPool

創建一個大小無限的線程池。此線程池支持定時以及周期性執行任務的需求。

publicclassScheduledThreadPoolDemo{publicstaticvoidmain(String[] args){ schedule(); scheduleAtFixedRate(); }privatestaticvoidschedule(){ ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);for (int i = 0; i < 100; i++) { executorService.schedule(new Runnable() {@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }, 1, TimeUnit.SECONDS); } executorService.shutdown(); }privatestaticvoidscheduleAtFixedRate(){ ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);for (int i = 0; i < 100; i++) { executorService.scheduleAtFixedRate(new Runnable() {@Overridepublicvoidrun(){ System.out.println(Thread.currentThread().getName() + " 執行"); } }, 1, 1, TimeUnit.SECONDS); } executorService.shutdown(); }}參考資料

《Java 並發編程實戰》《Java 並發編程的藝術》深入理解 Java 線程池:ThreadPoolExecutorjava 並發編程--Executor 框架

相關焦點

  • 深入理解 Java 線程池!
    這種問題使用線程池便可以很好的解決。通過線程池線程,銷毀及回收等交由線程池進行管理,就可以避免以上的問題。核心池大小是目標大小;線程池的實現試圖維護線程池的大小,即是沒有任務執行,池的大小也等於核心池的大小,並且在工作隊列充滿前,線程池都不會創建更多的線程。最大池的大小是可同時活動的線程數的上限。如果一個線程已經閒置的時間超過了存活時間,它將被線程池回收。
  • Java並發編程系列34|深入理解線程池(下)
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫本文是深入理解線程池下篇:線程池介紹Executor框架接口線程池狀態線程池參數線程池創建執行過程關閉線程池其他問題任務拒絕策略線程池中的線程初始化線程池容量的動態調整線程池的監控6.
  • 【線程池】java線程池ThreadPoolExecutor
    等按照需要創建了corePoolSize個線程之後,這些數量的線程即使閒置,也不會被線程池收回。這時即可以將這個值理解為線程池維護的最小線程數了。    maximumPoolSize 線程池維護的最大線程數。    keepAliveTime 當線程池中的線程數量大於corePoolSize,多出那部分數量的線程空閒keepAliveTime後會被收回。
  • 通過源碼解析,深入Java 線程池原理
    如果線程池太大,那麼被那些線程消耗的資源可能嚴重地影響系統性能。在線程之間進行切換將會浪費時間,而且使用超出比您實際需要的線程可能會引起資源匱乏問題,因為池線程正在消耗一些資源,而這些資源可能會被其它任務更有效地利用。
  • 「原創」Java並發編程系列33|深入理解線程池(上)
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫並發編程必不可少的線程池,接下來分兩篇文章介紹線程池,本文是第一篇。線程池將介紹如下內容:線程池介紹Executor框架接口線程池狀態線程池參數線程池創建
  • Java中線程池,你真的會用嗎?
    深入源碼分析Java線程池的實現原理》這篇文章中,我們介紹過了Java中線程池的常見用法以及基本原理。在文中有這樣一段描述:可以通過Executors靜態工廠構建線程池,但一般不建議這樣使用。關於這個問題,在那篇文章中並沒有深入的展開。作者之所以這麼說,是因為這種創建線程池的方式有很大的隱患,稍有不慎就有可能導致線上故障。本文我們就來圍繞這個問題來分析一下為什麼JDK自身提供的構建線程池的方式並不建議使用?
  • Java中線程池的簡單使用
    線程池可以用來幹什麼?線程池就可以幫助我們解決這個問題,他使線程可以重複使用,就是執行完一個任務線程不會被銷毀,而是可以繼續執行其他任務java中的線程池如何使用?java中線程池的使用java中有哪些線程池Java通過Executors提供四種線程池,分別為:
  • Java之線程池的簡單介紹
    現在小編來說說線程池的代碼實現:首先,java.util.concurrent.Executors:線程池的工廠類,用來生成線程池其次,Executors類中的靜態方法:>ExecutorService接口,返回的是ExecutorService接口的實現類對象,我們可以使用ExecutorService接口接收(面向接口編程)java.util.concurrent.ExecutorService:線程池接口,用來從線程池中獲取線程,調用start方法,執行線程任務。
  • Java入門 - - - 線程池的基本使用
    問題解決思路:我們可以用少量的線程保持工作且可以反覆執行任務(避免線程生命周期的損耗),這也就是要使用線程池。線程池的優點:加快響應速度(線程不必頻繁創建和銷毀);合理的利用CPU和內存這些有限資源;便於進行統一管理使用場景:比如伺服器接收大量請求時,或是開發過程中需要創建多個線程處理任務等。講解:核心類ThreadPoolExecutor。
  • 七個方面帶你玩轉Java線程池
    而這些離不開對線程池原理的深入了解。  本篇文章會從線程池的分類、線程池的創建、向線程池提交任務、關閉線程池、配置線程池、線程池的監控、線程池的實現原理七個方面講解線程池。當提交一個任務到線程池時,線程池會創建一個核心線程來執行任務,即使其他空閒的核心線程能夠執行新任務也會創建新的核心線程,而等到需要執行的任務數大於線程池核心線程的數量時就不再創建,這裡也可以理解為當核心線程的數量等於線程池允許的核心線程最大數量的時候,如果有新任務來,就不會創建新的核心線程。
  • 使用Executors,ThreadPoolExecutor,創建線程池,源碼分析理解
    TestThreadPoolExecutor 示例TestThreadPoolExecutor.javapackage io.ymq.thread.TestThreadPoolExecutor;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor
  • 手寫Java線程池(超詳細解說)
    ), 因為線程池自身執行也需要一個線程, 所以繼承Thread, 這樣可以在BasicThreadPool的構造方法中執行start(), run方法中執行創建線程的操作(線程池內部執行任務的線程); 創建線程取決於線程池設置的最大線程數, 核心線程數, 初始化線程數, 用戶提交的任務數;2.實現ThreadPool接口(該接口主要用於定義線程池的基本操作, 比如執行任務, 獲取線程池的一些基本屬性
  • 帶你一步步從源碼角度深入理解Java線程池(簡單易懂)
    1、使用線程池的好處:提高響應速度(減少了創建新線程的時間)降低資源消耗(重複利用線程池中線程,不需要每次都創建)便於線程進行管理,線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。
  • java新手揭秘:阿里巴巴為何禁止使用Executors來創建線程池
    當一個java新手從不斷地Curd階段跳出來之後,就會學習java的並發,並行等高階用法,自然就會用到線程、線程池,線程池的好處這裡就不做詳細解釋,你應該會學習到Executors創建線程池的四個方法, 分別是:newFixedThreadPool
  • 從使用到原理,探究Java線程池
    線程池的使用1.線程池的核心參數想掌握線程池首先要理解線程池構造函數的參數:逐個解釋這些參數是很難理解的,這裡我結合一張線程池處理的流程圖進行講解:newSingleThreadExecutor從字面上也好理解,這是一個單線程的線程池,它的構造參數如下(創建的時候不需要傳參,這裡指的是下一層調用線程池構造函數時的傳參):
  • java線程池核心類ThreadPoolExecutor概述
    我們使用線程池來解決這個問題,讓線程運行完不立即銷毀,並且重複使用,繼續執行其他的任務。使用線程池來管理線程,一方面使線程的創建更加規範,可以合理控制開闢線程的數量;另一方面線程的細節管理交給線程池處理,優化了資源的開銷。
  • java開發之Tomcat線程池優化
    前言:上期我們說到了jvm的內存優化,這期我們來說說tomcat的線程池優化,此思路同樣可用於c3p0等連接池tomcat線程池優化我們tomcat線程池的優化,其實就是最大限度的發揮tomcat的性能。即讓伺服器在保障性能的情況下並發最大並發:所有線程,在同一秒一起訪問同一個資源。
  • Java線程池其實看懂了也很簡單
    所以我很建議任何理論我們都需要自己去探究一下才好,自己實踐過的才有自己的理解而不是死記硬背,這樣才會經久不忘。線程池屬於開發中常見的一種池化技術,這類的池化技術的目的都是為了提高資源的利用率和提高效率,類似的HttpClient連接池,資料庫連接池等。
  • Java程式設計師幾年能實現月薪2萬,需要具備哪些技能?
    拋開工作經驗,項目經驗,學歷背景,單從技術點分析,哪些方面可以判斷一個java程式設計師的技術紮實程度,怎樣才能知道他值多少月薪呢?本文將為你解答:有人說這只能是大企業或者網際網路企業的工程師才能拿到。也許是的,小公司或者非網際網路企業拿兩萬的不太可能是碼農了,應該是已經轉管理後才有可能。
  • JAVA 線程池ThreadPoolExcutor原理探究
    下面將進入源碼分析,來深入理解 ThreadPoolExeCutor 的設計思想。 構造函數先來看構造函數:當提交一個任務時,如果當前核心線程池的線程個數沒有達到 corePoolSize,則會創建新的線程來執行所提交的任務,即使當前核心線程池有空閒的線程。如果當前核心線程池的線程個數已經達到了corePoolSize,則不再重新創建線程。如果調用了 prestartCoreThread() 或者 prestartAllCoreThreads(),線程池創建的時候所有的核心線程都會被創建並且啟動。