Java併發編程的藝術之九----線程池

第一:降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗

第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行

第三:提高線程的可管理性。線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,

還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。但是,要做到合理利用線程池,必須對其實現原理了如指掌。

1.線程池的實現原理

從圖中可以看出,當提交一個新任務到線程池時,線程池的處理流程如下。

1)線程池判斷核心線程池裏的線程是否都在執行任務。如果不是,則創建一個新的工作線程來執行任務。如果核心線程池裏的線程都在執行任務,則進入下個流程。

2)線程池判斷工作隊列是否已經滿。如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列裏。如果工作隊列滿了,則進入下個流程。

3)線程池判斷線程池的線程是否都處於工作狀態。如果沒有,則創建一個新的工作線程來執行任務。如果已經滿了,則交給飽和策略來處理這個任務。

Execute方法執行過程

①如果當前運行線程少於核心線程的容量,就創建新線程執行任務(獲取全局鎖)

②如果運行線程等於或多於核心線程容量,就將任務加入阻塞隊列

③如果阻塞隊列已滿,創建新線程處理任務

④如果超過最大線程數maximumPoolSize,任務將被拒絕,調用RejectedExecutionHandler.rejectedExecution()方法。

執行execute()方法時,儘可能避免獲取全局鎖,如果當前運行線程數大於等於corePoolSize,幾乎所有的execute方法都是執行步驟2,不需要獲取全局鎖

 

工作線程:線程池創建線程時,會將線程封裝成工作線程worker,worker執行完任務後,還會循環獲取工作隊列的任務來執行。

①execute方法創建一個線程時,會讓這個線程執行當前任務

②這個線程執行完上圖1的任務後,會反覆從BlockingQueue獲取任務執行

 

 

2.線程池的使用

2.1線程池的創建

可以通過ThreadPoolExecutor來創建一個線程池。

new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, milliseconds, runnableTaskQueue, handler);

①corePoolSize(核心線程池的基本大小):當提交一個任務到線程池時,線程池會創建一個線程來執行任務,即使其他空閒的基本線程能夠執行新任務也會創建線程,等到需要執行的任務數大於核心線程池基本大小時就不再創建。

②runnableTaskQueue(任務隊列):用於保存等待執行的任務阻塞隊列

ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue無界

③maximumPoolSize:線程池允許創建的最大線程數。如果隊列滿了,並且已創建的線程數小於最大線程數,則線程池會再創建新的線程執行任務。無界隊列沒有效果

④ThreadFactory:用於設置創建線程的工廠,可以通過線程工廠給每個創建出來的線程設置更有意義的名字。

⑤RejectedExecutionHandler(飽和策略):當隊列和線程池都滿了,說明線程池處於飽和狀態,那麼必須採取一種策略處理提交的新任務。這個策略默認情況下是AbortPolicy,表示無法處理新任務時拋出異常。

keepAliveTime(線程活動保持時間):線程池的工作線程空閒後,保持存活的時間。所以,如果任務很多,並且每個任務執行的時間比較短,可以調大時間,提高線程的利用率

TimeUnit(線程活動保持時間的單位):可選的單位有天(DAYS)、小時(HOURS)、分鐘(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和納秒(NANOSECONDS,千分之一微秒)

2.2 向線程池提交任務

Execute和submit

execute()方法用於提交不需要返回值的任務,所以無法判斷任務是否被線程池執行成功。

threadsPool.execute(new Runnable() {

@Override

public void run() {

// TODO Auto-generated method stub

}

});

 

 

submit()方法用於提交需要返回值的任務

一個future類型的對象,通過這個future對象可以判斷任務是否執行成功,並且可以通過future的get()方法來獲取返回值,get()方法會阻塞當前線程直到任務完成,

2.3線程池的監控

TaskCount:線程池需要執行的任務數

completeTaskCount:已完成的任務數

largestPoolSize:線程池裏曾經創建過的最大線程數

getPoolSize:線程池的線程數量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章