1. 程式人生 > >深入理解--執行緒池

深入理解--執行緒池

如果併發的執行緒數量很多,並且每個執行緒都是執行一個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷燬執行緒需要時間。

  那麼有沒有一種辦法使得執行緒可以複用,就是執行完一個任務,並不被銷燬,而是可以繼續執行其他的任務?

  在Java中可以通過執行緒池來達到這樣的效果。今天我們就來詳細講解一下Java的執行緒池,首先我們從最核心的ThreadPoolExecutor類中的方法講起,然後再講述它的實現原理,接著給出了它的使用示例,最後討論了一下如何合理配置執行緒池的大小。

  以下是本文的目錄大綱:

  一.Java中的ThreadPoolExecutor類

  二.深入剖析執行緒池實現原理

  三.使用示例

  四.如何合理配置執行緒池的大小 

  若有不正之處請多多諒解,並歡迎批評指正。

  請尊重作者勞動成果,轉載請標明原文連結:

  http://www.cnblogs.com/dolphin0520/p/3932921.html

一.Java中的ThreadPoolExecutor類

  java.uitl.concurrent.ThreadPoolExecutor類是執行緒池中最核心的一個類,因此如果要透徹地瞭解Java中的執行緒池,必須先了解這個類。下面我們來看一下ThreadPoolExecutor類的具體實現原始碼。

  在ThreadPoolExecutor類中提供了四個構造方法:

123456789101112131415public class ThreadPoolExecutor extends AbstractExecutorService {.....public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);...}

   從上面的程式碼可以得知,ThreadPoolExecutor繼承了AbstractExecutorService類,並提供了四個構造器,事實上,通過觀察每個構造器的原始碼具體實現,發現前面三個構造器都是呼叫的第四個構造器進行的初始化工作。

   下面解釋下一下構造器中各個引數的含義:

  • corePoolSize:核心池的大小,這個引數跟後面講述的執行緒池的實現原理有非常大的關係。在建立了執行緒池後,預設情況下,執行緒池中並沒有任何執行緒,而是等待有任務到來才建立執行緒去執行任務,除非呼叫了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預建立執行緒的意思,即在沒有任務到來之前就建立corePoolSize個執行緒或者一個執行緒。預設情況下,在建立了執行緒池後,執行緒池中的執行緒數為0,當有任務來之後,就會建立一個執行緒去執行任務,當執行緒池中的執行緒數目達到corePoolSize後,就會把到達的任務放到快取隊列當中;
  • maximumPoolSize:執行緒池最大執行緒數,這個引數也是一個非常重要的引數,它表示線上程池中最多能建立多少個執行緒;
  • keepAliveTime:表示執行緒沒有任務執行時最多保持多久時間會終止。預設情況下,只有當執行緒池中的執行緒數大於corePoolSize時,keepAliveTime才會起作用,直到執行緒池中的執行緒數不大於corePoolSize,即當執行緒池中的執行緒數大於corePoolSize時,如果一個執行緒空閒的時間達到keepAliveTime,則會終止,直到執行緒池中的執行緒數不超過corePoolSize。但是如果呼叫了allowCoreThreadTimeOut(boolean)方法,線上程池中的執行緒數不大於corePoolSize時,keepAliveTime引數也會起作用,直到執行緒池中的執行緒數為0;
  • unit:引數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:
複製程式碼
TimeUnit.DAYS;               //
TimeUnit.HOURS;             //小時
TimeUnit.MINUTES;           //分鐘
TimeUnit.SECONDS;           //
TimeUnit.MILLISECONDS;      //毫秒
TimeUnit.MICROSECONDS;      //微妙
TimeUnit.NANOSECONDS;       //納秒
複製程式碼
  • workQueue:一個阻塞佇列,用來儲存等待執行的任務,這個引數的選擇也很重要,會對執行緒池的執行過程產生重大影響,一般來說,這裡的阻塞佇列有以下幾種選擇:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue;

  ArrayBlockingQueue和PriorityBlockingQueue使用較少,一般使用LinkedBlockingQueue和Synchronous。執行緒池的排隊策略與BlockingQueue有關。

  • threadFactory:執行緒工廠,主要用來建立執行緒;
  • handler:表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務並丟擲RejectedExecutionException異常。 
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不丟擲異常。 
ThreadPoolExecutor.DiscardOldestPolicy:丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程)
ThreadPoolExecutor.CallerRunsPolicy:由呼叫執行緒處理該任務 

   具體引數的配置與執行緒池的關係將在下一節講述。

  從上面給出的ThreadPoolExecutor類的程式碼可以知道,ThreadPoolExecutor繼承了AbstractExecutorService,我們來看一下AbstractExecutorService的實現:

123456789101112131415161718192021222324252627public abstract class AbstractExecutorService implements ExecutorService {protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { };protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { };public Future<?> submit(Runnable task) {};public <T> Future<T> submit(Runnable task, T result) { };public <T> Future<T> submit(Callable<T> task) { };private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,boolean timed, long nanos)throws InterruptedException, ExecutionException, TimeoutException {};public <T> T invokeAny(Collection<? extends Callable<T>> tasks)throws InterruptedException, ExecutionException {};public <T> T invokeAny(Collection<? extends Callable<T>> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException {};public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)throws InterruptedException {};

相關推薦

Java核心(二)深入理解執行ThreadPool

本文你將獲得以下資訊: 執行緒池原始碼解讀 執行緒池執行流程分析 帶返回值的執行緒池實現 延遲執行緒池實現 為了方便讀者理解,本文會由淺入深,先從執行緒池的使用開始再延伸到原始碼解讀和原始碼分析等高階內容,讀者可根據自己的情況自主選擇閱讀順序和需要了解的章節。 一、執行緒池優點

Java併發--深入理解執行

為什麼需要執行緒池 在生產環境中,我們不能無限制的建立執行緒,主要原因如下: 執行緒建立與銷燬的代價並不低; 如果可執行的執行緒數量多於可用處理器的數量,有些執行緒將會閒置,大量閒置的執行緒會消耗系統資源(記憶體)並給垃圾收集器帶來壓力; 大量執行緒競爭C

深入理解--執行

如果併發的執行緒數量很多,並且每個執行緒都是執行一個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷燬執行緒需要時間。  那麼有沒有一種辦法使得執行緒可以複用,就是執行完一個任務,並不被銷燬,而是可以繼續執行其他的任務?  在Java中可以通過執行緒池來達到這樣的效果。

深入理解執行執行(圖文詳解)

關於執行緒和執行緒池的學習,我們可以從以下幾個方面入手:第一,什麼是執行緒,執行緒和程序的區別是什麼第二,執行緒中的基本概念,執行緒的生命週期第三,單執行緒和多執行緒第四,執行緒池的原理解析第五,常見的幾種執行緒池的特點以及各自的應用場景一、執行緒,程式執行流的最小執行單位,

【架構】Java併發程式設計 - 深入剖析執行

前言 如果我們要使用執行緒的時候就去建立一個,這樣雖然非常簡便,但是就會有一個問題: 如果併發的執行緒數量很多,並且每個執行緒都是執行一個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷燬執行緒需要時間。 那麼有沒有一種辦法使得執行緒可以複用

Java 併發程式設計深入學習——執行及其實現原理

Java執行緒池介紹   執行緒池,從字面含義來看,是指管理一組同構工作執行緒的資源池。執行緒池是與工作佇列(work Queue)密切相關的,其中工作佇列中儲存了所有等待執行的任務。工作者執行緒(Work Thread)的任務很簡單:從工作佇列中獲取一個任務,執行任務,然

深入剖析執行實現原理

1.執行緒池狀態     在ThreadPoolExecutor中定義了一個volatile變數,另外定義了幾個static final變量表示執行緒池的各個狀態: volatile int runState; static final int RUNNING =

如何優雅的使用和理解執行

前言 平時接觸過多執行緒開發的童鞋應該都或多或少了解過執行緒池,之前釋出的《阿里巴巴 Java 手冊》裡也有一條: 可見執行緒池的重要性。 簡單來說使用執行緒池有以下幾個目的: 執行緒是稀缺資源,不能頻繁的建立。 解耦作用;執行緒的創建於執行完全分開,方便維護。 應當將其放入一個池子中,可

通俗易懂地理解執行&&C++程式碼例項與講解

本機環境:win10   64位   vs2017 C++新手,程式碼寫得比較一般,高手見諒(抱拳)。 歡迎留言交流! 簡介執行緒池: 在介紹執行緒池之前,我們要首先知道多執行緒是啥。 單執行緒:就是說你現在有四件毫不相干的事情要分

理解執行的原理

1.關於執行緒池 執行緒池的技術背景 在面向物件程式設計中,建立和銷燬物件是很費時間的,因為建立一個物件要獲取記憶體資源或者其它更多資源。在Java中更是如此,虛擬機器將試圖跟蹤每一個物件,以便能夠在物件銷燬後進行垃圾回收。 所以提高服務

深入理解執行安全和可重入函式

執行緒安全 基本定義 執行緒安全:簡單來說執行緒安全就是多個執行緒併發同一段程式碼時,不會出現不同的結果,我們就可以說該執行緒是安全的; 執行緒不安全:說完了執行緒安全,執行緒不安全的問題就很好解

深入分析執行(二)—ThreadPoolExecutor常用方法

這4個類就是我們的主線。這裡我只顯示了public方法詳細介紹ThreadPoolExecutor的方法:方法shutdown() 和 shutdownNow()    shutdown :使當前未執行的執行緒繼續執行,而不再新增新的任務Task,該方法不會阻塞。    sh

深入學習執行原理

   在前面的文章:<<執行緒池原理初探>>中我們學習了執行緒池的基本用法和優點,並且從原始碼層面學習了執行緒池的內部資料結構以及執行狀態表徵方法,這是最基礎但是又很重要的一環,有了這一步鋪墊我們便可以開始進一步的原始碼學習之旅了。   本文會從如下幾個方面展開:   工作執

效能測試:深入理解執行數,併發量,TPS,看這一篇就夠了

併發數,執行緒數,吞吐量,每秒事務數(TPS)都是效能測試領域非常關鍵的資料和指標。 那麼他們之間究竟是怎樣的一個對應關係和內在聯絡? 測試時,我們經常容易將執行緒數等同於表述為併發數,這一表述正確嗎? 本文就將對效能領域的這些關鍵概念做一次探討。 文章可能會比較長,希望您保持耐心看完。   1.

含原始碼解析,深入Java 執行原理

從池化技術到底層實現,一篇文章帶你貫通執行緒池技術。 1、池化技術簡介 在系統開發過程中,我們經常會用到池化技術來減少系統消耗,提升系統性能。 在程式設計領域,比較典型的池化技術有: 執行緒池、連線池、記憶體池、物件池等。 物件池通過複用物件來減少建立物件、垃圾回收的開銷;連線池(資料庫連線池、Redis連線

【JUC】如何理解執行?第四種使用執行的方式

執行緒池的概念 執行緒池的主要工作的控制執行的執行緒的數量,處理過程種將任務放在佇列,執行緒建立後再啟動折現任務,如果執行緒數量超過了最大的數量,則超過部分的執行緒排隊等待,直到其他執行緒執行完畢後,從佇列種取出任務來執行。 處理流程: 1.執行緒池判斷核心執行緒池的執行緒是否全部在執行任務?   1.1 不

Java之執行原始碼深入理解

在前面的文章中,我們使用執行緒的時候就去建立一個執行緒,這樣實現起來非常簡便,但是就會有一個問題: 如果併發的執行緒數量很多,並且每個執行緒都是執行一個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷燬執行

深入理解Java多執行--執行(ThreadPool)

在java多執行緒開發中,我們需要使用執行緒的時候一般是建立一個Thread物件,然後呼叫start()方法去執行執行緒操作。這樣做沒有什麼問題,但是如果我們有很多工需要多個執行緒來非同步執行的時候,在我們建立了很多執行緒的情況下,會造成很大的效能方面的問題。 1.大量的執行緒的建立和銷燬,

深入理解Java執行(1):ThreadPoolExecutor整體流程梳理,建立worker相關方法

執行緒池作為一個執行緒的容器,主要的作用就是防止頻繁建立執行緒,節省時間資源和cpu資源。雖然一定程度上佔用了記憶體,但實際情況下利遠遠大於弊。 構造方法 public ThreadPoolExecutor( int corePoolSize, //核

深入理解Java執行原理分析與使用(尤其當執行佇列滿了之後事項)

在這裡借花獻佛了,那別人的東西學一學了。在我們的開發中“池”的概念並不罕見,有資料庫連線池、執行緒池、物件池、常量池等等。下面我們主要針對執行緒池來一步一步揭開執行緒池的面紗。使用執行緒池的好處1、降低資源消耗可以重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。2、提高響應速度當任務到達時,任務可以不需