1.直接提交 SynchronousQueuejava
它將任務直接提交給線程而不保存它們。在此,若是不存在可用於當即運行任務的線程,則試圖把任務加入隊列將失敗,所以會構造一個新的線程。此策略能夠避免在處理可能具備內部依賴性的請求集時出現鎖。直接提交一般要求無界 maximumPoolSizes 以免拒絕新提交的任務。當命令以超過隊列所能處理的平均數連續到達時,此策略容許無界線程具備增加的可能性。 SynchronousQueue線程安全的Queue,能夠存放若干任務(但當前只容許有且只有一個任務在等待),其中每一個插入操做必須等待另外一個線程的對應移除操做,也就是說A任務進入隊列,B任務必須等A任務被移除以後才能進入隊列,不然執行異常策略。你來一個我扔一個,因此說SynchronousQueue沒有任何內部容量。安全
好比:核心線程數爲2,最大線程數爲3;使用SynchronousQueue。多線程
當前有2個核心線程在運行,又來了個A任務,兩個核心線程沒有執行完當前任務,根據若是運行的線程等於或多於 corePoolSize,spa
則 Executor 始終首選將請求加入隊列,而不添加新的線程。因此A任務被添加到隊列,此時的隊列是SynchronousQueue,操作系統
當前不存在可用於當即運行任務的線程,所以會構造一個新的線程,此時又來了個B任務,兩個核心線程尚未執行完。.net
新建立的線程正在執行A任務,因此B任務進入Queue後,最大線程數爲3,發現沒地方仍了。就只能執行異常策略(RejectedExecutionException)。線程
2 無界隊列 如LinkedBlockingQueuecode
使用無界隊列(例如,不具備預約義容量的 LinkedBlockingQueue)將致使在全部核心線程都在忙時新任務在隊列中等待。這樣,建立的線程就不會超過 corePoolSize。(所以,maximumPoolSize 的值也就沒意義了。)也就不會有新線程被建立,都在那等着排隊呢。若是未指定容量,則它等於 Integer.MAX_VALUE。若是設置了Queue預約義容量,則當核心線程忙碌時,新任務會在隊列中等待,直到超過預約義容量(新任務沒地方放了),纔會執行異常策略。你來一個我接一個,直到我容不下你了。FIFO,先進先出。blog
好比:核心線程數爲2,最大線程數爲3;使用LinkedBlockingQueue(1),設置容量爲1。隊列
當前有2個核心線程在運行,又來了個A任務,兩個核心線程沒有執行完當前任務,根據若是運行的線程等於或多於 corePoolSize,
則 Executor 始終首選將請求加入隊列,而不添加新的線程。因此A任務被添加到隊列,此時的隊列是LinkedBlockingQueue,
此時又來了個B任務,兩個核心線程沒有執行完當前任務,A任務在隊列中等待,隊列已滿。因此根據若是沒法將請求加入隊列,則建立新的線程,
B任務被新建立的線程所執行,此時又來個C任務,此時maximumPoolSize已滿,隊列已滿,只能執行異常策略(RejectedExecutionException)。
3.有界隊列。
當使用有限的 maximumPoolSizes 時,有界隊列(如 ArrayBlockingQueue
)有助於防止資源耗盡,可是可能較難調整和控制。隊列大小和最大池大小可能須要相互折衷:使用大型隊列和小型池能夠最大限度地下降 CPU 使用率、操做系統資源和上下文切換開銷,可是可能致使人工下降吞吐量。若是任務頻繁阻塞(例如,若是它們是 I/O 邊界),則系統可能爲超過您許可的更多線程安排時間。使用小型隊列一般要求較大的池大小,CPU 使用率較高,可是可能遇到不可接受的調度開銷,這樣也會下降吞吐量。
爲java線程池默認的阻塞策略,不執行此任務,並且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute須要try catch,不然程序會直接退出。
直接拋棄,任務不執行,空方法
從隊列裏面拋棄head的一個任務,並再次execute 此task。
在調用execute的線程裏面執行此command,會阻塞入口
參考博文: