Java 線程池 隊列

原帖地址  http://automaticthoughts.iteye.com/blog/1612388

1.使用線程池的目的:

1.1減少使用與創建線程池的次數,每個線程都可以重複利用,可執行多個任務。
1.2可以更具當前手機系統的內存大小,來動態調整線程池裏面固定的線程數量,造成阻塞,排隊,不會在線程上浪費過多的內存
同時使用線程的時候,我們用的是用來請求服務器,造成服務器過大的負擔
2.線程池的使用
在Java JDK1.5之後關於線程池的使用有了很大的改善,在Java.util.concurrent包中介紹了對於線程池的使用,XMPP協議的使用着,

Asmack有3個關於線程池的使用的地方,一個是關於發送心跳包來維繫與服務器的長鏈接的地方,一個是接收消息的阻塞線程隊列,一個是發送

Message 字節流的地方,
Java中線程池的最頂部的接口是Executor,嚴格來將Executor並不是一個線程池,而是一個執行線程的工具,真正的線程池接口是

ExecutorService
Executor中幾個比較重要的類相關介紹:
ExecutorService,ScheduleExecutorService,ThreadPoolExecutor,ScheduledThreadPoolExecutor:
ExecutorService:就是一個真正的線程池的接口
ScheduleExecutorService:與Timer相似,用來解決需要重複執行的任務線程管理
ThreadPoolExecutor:ExecutorService的默認實現類
ScheduledThreadPoolExecutor:週期性重複調用的線程池管理,例如Android中的循環切換切換廣告欄圖片,這個任務就是循環重複的

,在執行完一次之後,需要重複循環調用Schedule本身就是目錄或者時刻表的意思
Executor類裏面提供了一些靜態的工廠類,用來創建不同需求的線程池
2.1 newSingleThreadExecutor: 創建一個只存在單個線程的線程池,也就是單個線程執行所有的任務,如果唯一的那一條線程出現異

常Interruput,那麼會有一個新的線程來代替之前的線程,此線程池保證所有的任務按照任務的提交順序執行
2.2 newFixedThreadPool:創建固定大小的線程池,每次提交一個任務就在線程池中添加一條,知道線程池中的數量達到創建是設置的

數目,線程池的大小一旦達到最大值就沒辦法改變,除非線程池中的某條線程出現異常,纔會創建一個備胎,備胎就可以轉正了,
2.3 newCacheThreadPool:創建一個可以緩存的線程池,當需要處理的任務添加的時候能夠智能的添加新線程來處理任務,那麼就會回

收部分不執行的線程,或者處於休閒狀態的線程池(60秒的時間內,啥都沒幹的線程),線程池的大小完全依賴於JVM
2.4 newScheduledThreaPool:創建一個沒有大小限制的線程池,此線程中池用來週期性重複的執行某條線程

3 關於ThreadPoolExecutor
ThreadPoolExecutor的完整構造與簽名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,

TimeUnit unit)
構造函數中的參數意義:corePoolSize 線程池中保存的線程數量,包括空閒線程
maximumPoolSize 線程池中保存線程的最大值
keepAliveTime 當線程池中的線程數量大於corePoolSize ,終止多餘的空閒線程,等待新任務的最長時間,其實表示的是多長時間把

線程分類爲空閒線程
unit 構造函數中keepAliveTime的時間單位
4 queue的三種類型
排隊通常有三種通用的策略:
4.1直接提交
工作隊列的默認選項是 SynchronousQueue,它將任務直接提交給線程而不保持它們。在此,如果不存在可用於立即運行任

務的線程,則試圖把任務加入隊列將失敗,因此會構造一個新的線程。此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。直接提

交通常要求無界 maximumPoolSizes 以避免拒絕新提交的任務。當命令以超過隊列所能處理的平均數連續到達時,此策略允許無界線程具有增

長的可能性。
4.2無界隊列
使用無界隊列(例如,不具有預定義容量的 LinkedBlockingQueue)將導致在所有 corePoolSize 線程都忙時新任務在隊列

中等待。這樣,創建的線程就不會超過 corePoolSize。(因此,maximumPoolSize 的值也就無效了。)當每個任務完全獨立於其他任務,即

任務執行互不影響時,適合於使用無界隊列;例如,在 Web 頁服務器中。這種排隊可用於處理瞬態突發請求,當命令以超過隊列所能處理的

平均數連續到達時,此策略允許無界線程具有增長的可能性。
4.3有界隊列
當使用有限的 maximumPoolSizes 時,有界隊列(如 ArrayBlockingQueue)有助於防止資源耗盡,但是可能較難調整和控

制。隊列大小和最大池大小可能需要相互折衷:使用大型隊列和小型池可以最大限度地降低 CPU 使用率、操作系統資源和上下文切換開銷,

但是可能導致人工降低吞吐量。如果任務頻繁阻塞(例如,如果它們是 I/O 邊界),則系統可能爲超過您許可的更多線程安排時間。使用小

型隊列通常要求較大的池大小,CPU 使用率較高,但是可能遇到不可接受的調度開銷,這樣也會降低吞吐量。

5 BlockingQueue的選擇
5.1使用直接提交策略,也即SynchronousQueue。在某次添加元素後必須等待其他線程取走後才能繼續添加。
5.2使用無界隊列策略,即LinkedBlockingQueue 這個就拿newFixedThreadPool來說,根據前文提到的規則:
如果運行的線程少於 corePoolSize,則 Executor 始終首選添加新的線程,而不進行排隊。那麼當任務繼續增加,會發生什麼呢?
5.3有界隊列,使用ArrayBlockingQueue。

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