Java 執行緒池原理和佇列詳解
http://blog.csdn.net/xx326664162/article/details/51701508
執行緒池的框架圖:
1、Executor任務提交介面與Executors工具類
Executor框架同Java.util.concurrent.Executor 介面在Java 5中被引入。Executor框架是一個根據一組執行策略呼叫,排程,執行和控制的非同步任務的框架。Executor存在的目的是提供一種將“任務提交”與”任務如何執行”分離開來的機制。定義如下:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> Executor { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> execute(Runnable command); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
雖然只有一個方法,但是卻為靈活且強大的非同步任務執行框架提供了基礎。它提供了一種標準的方法將任務的提交過程與執行過程解耦開來,並用Runnable來表示任務。
那麼我們怎麼得到Executor物件呢?這就是接下來要介紹的Exectors類了。
Executors為Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable類提供了一些工具方法,類似於集合中的Collections類的功能。Executors方便的建立執行緒池。
1、newCachedThreadPool
該執行緒池比較適合沒有固定大小並且比較快速就能完成的小任務,它將為每個任務建立一個執行緒。那這樣子它與直接建立執行緒物件(new Thread())有什麼區別呢?看到它的第三個引數60L和第四個引數TimeUnit.SECONDS了嗎?好處就在於60秒內能夠重用已建立的執行緒。
下面是Executors中的newCachedThreadPool()的原始碼:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> ExecutorService <span class="hljs-title" style="box-sizing: border-box;">newCachedThreadPool</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, Integer.MAX_VALUE, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span>L, TimeUnit.SECONDS, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SynchronousQueue<Runnable>()); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
2、 newFixedThreadPool
使用的Thread物件的數量是有限的,如果提交的任務數量大於限制的最大執行緒數,那麼這些任務將排隊,然後當有一個執行緒的任務結束之後,將會根據排程策略繼續等待執行下一個任務。
下面是Executors中的newFixedThreadPool()的原始碼:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> ExecutorService <span class="hljs-title" style="box-sizing: border-box;">newFixedThreadPool</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nThreads) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor(nThreads, nThreads, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>L, TimeUnit.MILLISECONDS,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LinkedBlockingQueue<Runnable>()); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
3、newSingleThreadExecutor
執行緒數量為1的FixedThreadPool,如果提交了多個任務,那麼這些任務將會排隊,每個任務都會在下一個任務開始之前執行結束,所有的任務將會使用相同的執行緒。下面是Executors中的newSingleThreadExecutor()的原始碼:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> ExecutorService <span class="hljs-title" style="box-sizing: border-box;">newSingleThreadExecutor</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> FinalizableDelegatedExecutorService (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>L, TimeUnit.MILLISECONDS, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LinkedBlockingQueue<Runnable>())); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
4、newScheduledThreadPool
建立一個固定長度的執行緒池,而且以延遲或定時的方式來執行任務。
通過如上配置的執行緒池的建立方法原始碼,我們可以發現:
1> 除了CachedThreadPool使用的是直接提交策略的緩衝佇列以外,其餘兩個用的採用的都是無界緩衝佇列,也就說,FixedThreadPool和SingleThreadExecutor建立的執行緒數量就不會超過 corePoolSize。
2> 三個執行緒池採用的ThreadPoolExecutor構造方法都是同一個,使用的都是預設的ThreadFactory和handler:
<code class="hljs java has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> RejectedExecutionHandler defaultHandler = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AbortPolicy(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">ThreadPoolExecutor</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> corePoolSize, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> maximumPoolSize, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>
也就說三個執行緒池建立的執行緒物件都是同組,優先權等級為正常的Thread.NORM_PRIORITY(5)的非守護執行緒,使用的被拒絕任務處理方式是直接丟擲異常的AbortPolicy策略(前面有介紹)。
二、ExecutorService任務週期管理介面
Executor的實現通常都會建立執行緒來執行任務,但是使用非同步方式來執行任務時,由於之前提交任務的狀態不是立即可見的,所以如果要關閉應用程式時,就需要將受影響的任務狀態反饋給應用程式。
為了解決執行服務的生命週期問題,Executor擴充套件了EecutorService介面,添加了一些用於生命週期管理的方法。如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ExecutorService</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Executor</span> {</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> shutdown(); List<Runnable> shutdownNow(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> isShutdown(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> isTerminated(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> awaitTermination(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> timeout, TimeUnit unit) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> InterruptedException; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 省略部分方法 </span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
三、ThreadPoolExecutor執行緒池實現類
先來看一下這個類中定義的重要變數,如下:
<code class="hljs java has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> BlockingQueue<Runnable> workQueue; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 阻塞佇列 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ReentrantLock mainLock = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ReentrantLock(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 互斥鎖 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> HashSet<Worker> workers = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> HashSet<Worker>();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 執行緒集合.一個Worker對應一個執行緒 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Condition termination = mainLock.newCondition();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 終止條件 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> largestPoolSize; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 執行緒池中執行緒數量曾經達到過的最大值。 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> completedTaskCount; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 已完成任務數量 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> ThreadFactory threadFactory; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ThreadFactory物件,用於建立執行緒。 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> RejectedExecutionHandler handler;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 拒絕策略的處理控制代碼 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> keepAliveTime; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 執行緒池維護執行緒所允許的空閒時間 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> allowCoreThreadTimeOut; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> corePoolSize; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 執行緒池維護執行緒的最小數量,哪怕是空閒的 </span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> maximumPoolSize; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 執行緒池維護的最大執行緒數量 </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
其中有幾個重要的規則需要說明一下:
1、 corePoolSize與maximumPoolSize
由於ThreadPoolExecutor 將根據 corePoolSize和 maximumPoolSize設定的邊界自動調整池大小,當新任務在方法 execute(java.lang.Runnable) 中提交時:
-
如果執行的執行緒少於 corePoolSize,則建立新執行緒來處理請求,即使其他輔助執行緒是空閒的;
-
如果執行的執行緒等於或多於 corePoolSize 而少於 maximumPoolSize,
- 佇列已滿:建立新的執行緒去處理請求
- 佇列未滿:將任務加入佇列
-
如果執行的執行緒多於corePoolSize 並且等於maximumPoolSize,
- 佇列已滿:通過handler所指定的策略來處理新請求;
- 佇列未滿:將任務加入佇列
-
如果將 maximumPoolSize 設定為基本的無界值(如 Integer.MAX_VALUE),則併發任務的數量沒有限制。
處理任務的優先順序為:
- 核心執行緒corePoolSize > 任務佇列workQueue > 最大執行緒maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。
- 當池中的執行緒數大於corePoolSize的時候,多餘的執行緒會等待keepAliveTime長的時間,如果無請求可處理就自行銷燬。
2、workQueue 執行緒池所使用的緩衝佇列
該緩衝佇列的長度決定了能夠緩衝的最大數量,緩衝佇列有三種通用策略:
1、 直接提交。
工作佇列的預設選項是 SynchronousQueue,它將任務直接提交給執行緒而不保持它們。
在此,如果不存在可用於立即執行任務的執行緒,則試圖把任務加入佇列將失敗,因此會構造一個新的執行緒。
此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。直接提交通常要求無界 maximumPoolSizes 以避免拒絕新提交的任務。當命令以超過佇列所能處理的平均數連續到達時,此策略允許無界執行緒具有增長的可能性;
2、 無界佇列
使用無界佇列(例如,不具有預定義容量的 LinkedBlockingQueue)將導致在所有 corePoolSize 執行緒都忙時,新任務將在佇列中等待。這樣,建立的執行緒數量就不會超過 corePoolSize。(因此,maximumPoolSize 的值也就無效了。)
當每個任務完全獨立於其他任務,即任務執行互不影響時,適合於使用無界佇列;例如,在 Web 頁伺服器中。這種排隊可用於處理瞬態突發請求,當命令以超過佇列所能處理的平均數連續到達時,此策略允許無界執行緒具有增長的可能性;
3、 有界佇列
當使用有限的 maximumPoolSizes 時,有界佇列(如 ArrayBlockingQueue)有助於防止資源耗盡,但是可能較難調整和控制。
佇列大小和最大池大小可能需要相互折衷:使用大型佇列和小型池可以最大限度地降低 CPU 使用率、作業系統資源和上下文切換開銷,但是可能導致人工降低吞吐量。如果任務頻繁阻塞(例如,如果它們是 I/O 邊界),則系統可能為超過您許可的更多執行緒安排時間。使用小型佇列通常要求較大的池大小,CPU 使用率較高,但是可能遇到不可接受的排程開銷,這樣也會降低吞吐量.
舉例:
例子一:使用直接提交策略,也即SynchronousQueue。
首先SynchronousQueue是無界的,也就是說他儲存任務的能力是沒有限制的,但是由於該Queue本身的特性,在某次新增元素後必須等待其他執行緒取走後才能繼續新增。在這裡不是核心執行緒便是新建立的執行緒,但是我們試想一樣下,下面的場景。
我們使用一下引數構造ThreadPoolExecutor:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, TimeUnit.SECONDS, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SynchronousQueue<Runnable>(), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RecorderThreadFactory(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CookieRecorderPool"</span>), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor.CallerRunsPolicy()); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
假設當前核心執行緒已經有2個正在執行.
-
此時來了一個任務(A),根據前面介紹的“如果執行的執行緒等於或多於 corePoolSize,則 Executor 始終首選將請求加入佇列,而不新增新的執行緒。”,所以A被新增到queue中。
-
又來了一個任務(B),且核心2個執行緒還沒有忙完。接下來首先嚐試1中描述,但是由於使用的SynchronousQueue,所以一定無法加入進去。
-
此時便滿足了上面提到的“如果無法將請求加入佇列,則建立新的執行緒,除非建立此執行緒超出maximumPoolSize,在這種情況下,任務將被拒絕。”,所以必然會新建一個執行緒來執行這個任務。
-
但是如果這三個任務都還沒完成,繼續來了一個任務,queue中無法插入(任務A還在queue中),而執行緒數達到了maximumPoolSize,所以只好執行異常策略了。
為了避免這種情況:,所以在使用SynchronousQueue通常要求maximumPoolSize是無界的(如果希望限制就直接使用有界佇列)。對於使用SynchronousQueue的作用jdk中寫的很清楚:此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。
如果你的任務A1,A2有內部關聯,A1需要先執行,那麼先提交A1,再提交A2,當使用SynchronousQueue我們可以保證,A1必定先被執行,在A1麼有被執行前,A2不可能新增入queue中
例子二:使用無界佇列策略,即LinkedBlockingQueue
拿newFixedThreadPool來說,根據前文提到的規則:
- 如果執行的執行緒少於 corePoolSize,則 Executor 始終首選新增新的執行緒,而不進行排隊。
那麼當任務繼續增加,會發生什麼呢?
- 如果執行的執行緒等於或多於 corePoolSize,則 Executor 始終首選將請求加入佇列,而不新增新的執行緒。
OK,此時任務變加入佇列之中了,那什麼時候才會新增新執行緒呢?
- 如果無法將請求加入佇列,則建立新的執行緒,除非建立此執行緒超出 maximumPoolSize,在這種情況下,任務將被拒絕。
無界佇列不會出現無法加入佇列的情況。不像SynchronousQueue那樣有其自身的特點,對於無界佇列來說,總是可以加入的(資源耗盡,當然另當別論)。
換句說,永遠也不會觸發產生新的執行緒!執行緒數一直都是corePoolSize大小。忙完當前的執行緒,就從佇列中拿任務開始執行。如果任務執行的時長比較長,而新增任務的速度遠遠超過處理任務的速度,任務佇列就會瘋長,任務記憶體很快就會爆掉
例子三:有界佇列,使用ArrayBlockingQueue。
這個是最為複雜的使用,所以JDK不推薦使用也有些道理。與上面的相比,最大的特點便是可以防止資源耗盡的情況發生。
舉例來說,請看如下構造方法:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor( <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, TimeUnit.SECONDS, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayBlockingQueue<Runnable>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RecorderThreadFactory(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CookieRecorderPool"</span>), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ThreadPoolExecutor.CallerRunsPolicy()); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
假設,所有的任務都永遠無法執行完。
- 對於首先來的A,B來說直接執行
- 如果來了C,D,他們會被放到queu中
- 如果接下來再來E,F,則增加執行緒執行E,F。
- 但是如果再來任務,佇列無法再接受了,執行緒數也到達最大的限制了,所以就會使用拒絕策略來處理。
3、ThreadFactory
使用 ThreadFactory 建立新執行緒。如果沒有另外說明,則在同一個 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 建立執行緒,並且這些執行緒具有相同的 NORM_PRIORITY 優先順序和非守護程序狀態。
通過提供不同的 ThreadFactory,可以改變執行緒的名稱、執行緒組、優先順序、守護程序狀態等等。如果從 newThread 返回 null 時 ThreadFactory 未能建立執行緒,則執行程式將繼續執行,但不能執行任何任務。
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> ThreadFactory { Thread newThread(Runnable r); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
而構造方法中的threadFactory物件,是通過 Executors.defaultThreadFactory()返回的。Executors.java中的defaultThreadFactory()原始碼如下:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> ThreadFactory <span class="hljs-title" style="box-sizing: border-box;">defaultThreadFactory</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DefaultThreadFactory(); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
在DefaultThreadFactory類中實現了ThreadFactory介面並對其中定義的方法進行了實現,如下:
<code class="hljs axapta has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DefaultThreadFactory</span> <span class="hljs-inheritance" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span></span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ThreadFactory</span> {</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> AtomicInteger poolNumber = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AtomicInteger(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ThreadGroup <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">group</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> AtomicInteger threadNumber = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> AtomicInteger(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); <span class="hljs-ke
相關推薦
Java 執行緒池原理和佇列詳解
http://blog.csdn.net/xx326664162/article/details/51701508 執行緒池的框架圖: 1、Executor任務提交介面與Executors工具類 Executor框架同Java.util.
Java執行緒池原理與例項詳解
Wiki 採用new Thread的方式產生多執行緒,可能有以下一些問題: 執行緒的建立和銷燬開銷很大,尤其是有些執行緒的存在時間較短; 執行緒的建立和銷燬過程中伴隨著CPU線上程間的切換,開銷很大; 執行緒池的優點有: 減少了
Java執行緒池原理和使用
為什麼要用執行緒池? 諸如 Web 伺服器、資料庫伺服器、檔案伺服器或郵件伺服器之類的許多伺服器應用程式都面向處理來自某些遠端來源的大量短小的任務。請求以某種方式到達伺服器,這種方式可能是通過網路協議(例如 HTTP、FTP 或 POP)、通過 JMS 佇列或者可能通過
java執行緒池ThreadPoolExecutor類使用詳解
在《阿里巴巴java開發手冊》中指出了執行緒資源必須通過執行緒池提供,不允許在應用中自行顯示的建立執行緒,這樣一方面是執行緒的建立更加規範,可以合理控制開闢執行緒的數量;另一方面執行緒的細節管理交給執行緒池處理,優化了資源的開銷。而執行緒池不允許使用Executors去建立,而要通過ThreadPoolExe
java執行緒池的使用與詳解
正在執行task 0 執行緒池中執行緒數目:1,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0 執行緒池中執行緒數目:2,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0 正在執行task 1 執行緒池中執行緒數目:3,佇列中等待執行的任務數目:0,已執行玩別的任務數目:0 正在執行task 2
java執行緒池ThreadPoolExecutor和阻塞佇列BlockingQueue,Executor, ExecutorService
ThreadPoolExecutor 引數最全的建構函式 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
深入理解Java執行緒池原理分析與使用(尤其當執行緒佇列滿了之後事項)
在這裡借花獻佛了,那別人的東西學一學了。在我們的開發中“池”的概念並不罕見,有資料庫連線池、執行緒池、物件池、常量池等等。下面我們主要針對執行緒池來一步一步揭開執行緒池的面紗。使用執行緒池的好處1、降低資源消耗可以重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。2、提高響應速度當任務到達時,任務可以不需
執行緒池原理--任務佇列BlockingQueue
文章目錄 執行緒池原理--任務佇列BlockingQueue 類繼承體系 介面抽象方法 實現類 ArrayBlockingQueue SynchronousQueue LinkedBlockin
Java執行緒池原理及使用
java中的執行緒池是運用場景最多的併發框架。在開發過程中,合理的使用執行緒池能夠帶來下面的一些好處: 1、降低資源的消耗。 2、提高響應速度。 3、提高執行緒的可管理型。 1.1、執行緒池ThreadPoolExecutor工作原理 講解之前,我們先看一張原理
Java常用四大執行緒池用法以及ThreadPoolExecutor詳解
為什麼用執行緒池? 1.建立/銷燬執行緒伴隨著系統開銷,過於頻繁的建立/銷燬執行緒,會很大程度上影響處-理效率 2.執行緒併發數量過多,搶佔系統資源從而導致阻塞 3.對執行緒進行一些簡單的管理 在Java中,執行緒池的概念是Executor這個介面,具體實現為ThreadPoolE
java執行緒池原理(入門版)——看完還不懂我直播吃香
網上關於java執行緒池的部落格,大多是直接分析ThreadPoolExecutor類的實現,但是他們就像是做中文翻譯一樣,但是很少有講到本質的東西。 這篇部落格從根本出發,看完可以自己實現一個簡單執行緒池。下面正式開始。 一、我們知道,用java建立一條新執行
徹底弄懂 Java 執行緒池原理
概述 這篇文章是我在閱讀原始碼時整理的一些筆記,對原始碼的關鍵點進行了比較詳細的註釋,然後加上一些自己對執行緒池機制的理解。最終目的是要弄清楚下面這些問題: 執行緒池有 execute() 和 submit() 方法,執行機制分別是什麼? 如何新建執行緒? 任務如何執行? 執行緒如何銷燬
多執行緒——Java執行緒池原理深入
上次我們簡單瞭解了一下什麼是執行緒池以及Java中幾種型別的執行緒池,今天我們來深入剖析一下執行緒池的原理。 1、構造 1. 執行緒池管理器(ThreadPoo
Java執行緒池原理及四種執行緒池的使用
一、執行緒池簡介: 多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。 假設一個伺服器完成一項任務所需
併發(2)--java執行緒池原理
執行緒池Execotors工具可以建立普通的執行緒池以及schedule排程任務的排程池。使用執行緒池的一個優點就是: 1、執行緒是稀缺資源,使用執行緒池可以減少建立和銷燬執行緒的次數
Java執行緒池原理淺析
什麼是執行緒池? 為了避免頻繁重複的建立和銷燬執行緒,我們可以讓這些執行緒進行復用,線上程池中,總會有活躍的執行緒在佔用,但是執行緒池中也會存在沒有佔用的執行緒,這些執行緒處於空閒狀態,當有任務的時候會從池子裡面拿去一個執行緒來進行使用,當完成工作後,並沒有銷燬執行緒,而是將將執行緒放回到池子中去。 執行緒
含原始碼解析,深入Java 執行緒池原理
從池化技術到底層實現,一篇文章帶你貫通執行緒池技術。 1、池化技術簡介 在系統開發過程中,我們經常會用到池化技術來減少系統消耗,提升系統性能。 在程式設計領域,比較典型的池化技術有: 執行緒池、連線池、記憶體池、物件池等。 物件池通過複用物件來減少建立物件、垃圾回收的開銷;連線池(資料庫連線池、Redis連線
java執行緒池原理解析
五一假期大雄看了一本《java併發程式設計藝術》,瞭解了執行緒池的基本工作流程,竟然發現執行緒池工作原理和網際網路公司運作模式十分相似。 ## 執行緒池處理流程 ![執行緒池任務執行流程](https://img2020.cnblogs.com/blog/1128201/202005/1128201-20
JUC(4)---java執行緒池原理及原始碼分析
執行緒池,既然是個池子裡面肯定就裝很多執行緒。 如果併發的請求數量非常多,但每個執行緒執行的時間很短,這樣就會頻繁的建立和銷燬 執行緒,如此一來會大大降低系統的效率。可能出現伺服器在為每個請求建立新執行緒和銷燬線 程上花費的時間和消耗的系統資源要比處理實際的使用者請求的時間和資源更多。因此Java中提供執行緒
Java執行緒池原理及分析
執行緒池是很常用的併發框架,幾乎所有需要非同步和併發處理任務的程式都可用到執行緒池。 **使用執行緒池的好處如下**: 1. 降低資源消耗:可重複利用已建立的執行緒池,降低建立和銷燬帶來的消耗; 1. 提高響應速度:任務到達時,可立即執行,無需等待執行緒建立; 1. 提高執行緒的可管理性:執行緒池可對執行緒統