線程池
策略
- 當(dāng)線程數(shù)量未達(dá)到核心線程數(shù)量,直接啟動(dòng)一個(gè)核心線程來執(zhí)行任務(wù)。
- 如果線程數(shù)量已達(dá)到或者超過核心線程的數(shù)量,任務(wù)被插入到任務(wù)隊(duì)列中排隊(duì)執(zhí)行。
- 如果在步驟2中無法將任務(wù)插入到任務(wù)隊(duì)列中,這往往是由于任務(wù)隊(duì)列已滿,這時(shí)候如果線程數(shù)量未達(dá)到線程池規(guī)定的最大值,會(huì)立刻啟動(dòng)一個(gè)非核心線程來執(zhí)行任務(wù)。
- 如果步驟3中線程數(shù)量達(dá)到最大值,就拒絕執(zhí)行此任務(wù)。
模式
并發(fā)編程中經(jīng)常使用消費(fèi)者和生產(chǎn)者模式,通過一個(gè)容器來解決生產(chǎn)者和消費(fèi)者的強(qiáng)耦合問題。大多數(shù)設(shè)計(jì)模式都會(huì)找出一個(gè)第三者進(jìn)行解耦。
優(yōu)點(diǎn)
- 重用線程池中的線程
- 有效控制線程池的最大并發(fā)數(shù)
- 對(duì)線程進(jìn)行有效的管理,并提供定時(shí)執(zhí)行及制定間隔循環(huán)執(zhí)行等功能。
備注
如果已知曉策略,沒有必要記優(yōu)點(diǎn)。因?yàn)閮?yōu)點(diǎn)可直接由策略推導(dǎo)出來。
Executor框架
Executor作為用戶級(jí)的調(diào)度器,用于將任務(wù)映射為固定數(shù)量的線程。Executor框架主要由3大部分組成:
- 任務(wù)。包括被執(zhí)行任務(wù)需要實(shí)現(xiàn)的接口:Runnable或Callable接口。Runnable不返回結(jié)果,而Callable返回。
- 任務(wù)的執(zhí)行。包括任務(wù)執(zhí)行機(jī)制的核心接口Executor,以及繼承自Executor的ExecutorService接口。ThreadPoolExecutor及ScheduledThreadPoolExecutor實(shí)現(xiàn)了ExecutorService接口。ScheduledThreadPoolExecutor主要用來執(zhí)行定期或延遲的任務(wù)。
- 異步計(jì)算的結(jié)果。包括接口Future和實(shí)現(xiàn)Future接口的FutureTask接口。FutureTask是一個(gè)可對(duì)任務(wù)進(jìn)行狀態(tài)干預(yù)的Runnable異步對(duì)象。包括超時(shí)處理/取消任務(wù)/同步狀態(tài)等干預(yù)。
注意參數(shù)
keepAliveTime
線程活動(dòng)保持時(shí)間。線程池中非核心的工作線程空閑后保持存活時(shí)間。默認(rèn)核心線程會(huì)在線程池中一直存活,即使處于閑置狀態(tài)。
線程運(yùn)行狀態(tài)變遷

(1)BLOCKED(等待獲取鎖時(shí)進(jìn)入的狀態(tài))
synchronized
(2)WAITING(通過wait方法進(jìn)入的等待)
當(dāng)wait,join,park方法調(diào)用時(shí),進(jìn)入waiting狀態(tài)。前提是這個(gè)線程已經(jīng)擁有鎖了。進(jìn)入該狀態(tài)表示當(dāng)前線程需要等待其他線程做出一些特定動(dòng)作(通知或中斷)。
blocked和waiting狀態(tài)的區(qū)別是:
A、blocked是虛擬機(jī)認(rèn)為程序還不能進(jìn)入某個(gè)區(qū)域,因?yàn)橥瑫r(shí)進(jìn)去就會(huì)有問題,這是一塊臨界區(qū)。
B、發(fā)生wait等操作的先決條件是要進(jìn)入臨界區(qū),也就是線程已經(jīng)拿到鎖了,自己可能進(jìn)去做了一些事情,但此時(shí)通過判定業(yè)務(wù)上的參數(shù),發(fā)現(xiàn)還有一些其他配合的資源沒有準(zhǔn)備充分,那么自己就等等再做其他事情。
(3)TIMED_WAITING(通過sleep或wait timeout方法進(jìn)入的限期等待的狀態(tài))
通過wait(t),sleep(t),join(t),parkNanos,parkUntil等方法進(jìn)入此狀態(tài)。當(dāng)時(shí)間達(dá)到時(shí)觸發(fā)線程回到工作狀態(tài)Runnable。
Thread.yield( )方法會(huì)將當(dāng)前線程的可執(zhí)行時(shí)間釋放,從運(yùn)行中的狀態(tài)變?yōu)榫途w狀態(tài)。
Interrupted中斷
中斷不屬于狀態(tài),中斷可以理解為線程的一個(gè)標(biāo)識(shí)位屬性,表示一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作。
在waiting狀態(tài)下,如果發(fā)生了interrupt操作,則處于該狀態(tài)的線程在內(nèi)部會(huì)拋出一個(gè)InterruptedException,這個(gè)異常應(yīng)當(dāng)在run方法內(nèi)捕獲,使得run方法正常地執(zhí)行完成,當(dāng)然捕獲異常后,是決定讓線程繼續(xù)運(yùn)行,還是結(jié)束等要根據(jù)業(yè)務(wù)場(chǎng)景才處理。
interrupt只對(duì)處于waiting或timed_waiting狀態(tài)的線程起作用,對(duì)其他狀態(tài)不起作用。
并發(fā)/并行/線程/異步
并行(parallel):在操作系統(tǒng)中,一組程序按獨(dú)立異步的速度執(zhí)行,無論從微觀還是宏觀,程序都是一起執(zhí)行的。
并發(fā)(concurrent):在操作系統(tǒng)中,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間,且這幾個(gè)程序都是在同一個(gè)處理機(jī)上運(yùn)行,但任一個(gè)時(shí)刻點(diǎn)上只有一個(gè)程序在處理機(jī)上運(yùn)行。其中兩種并發(fā)關(guān)系分別是同步和互斥:
2.1 互斥:進(jìn)程間相互排斥的使用臨界資源的現(xiàn)象,就叫互斥。
2.2 同步:進(jìn)程之間的關(guān)系不是相互排斥臨界資源的關(guān)系,而是相互依賴的關(guān)系。進(jìn)一步的說明:就是前一個(gè)進(jìn)程的輸出作為后一個(gè)進(jìn)程的輸入,當(dāng)?shù)谝粋€(gè)進(jìn)程沒有輸出時(shí)第二個(gè)進(jìn)程必須等待。具有同步關(guān)系的一組并發(fā)進(jìn)程相互發(fā)送的信息稱為消息或事件。
并行的關(guān)鍵是擁有同時(shí)處理多個(gè)任務(wù)的能力。而并行的關(guān)鍵是擁有處理多個(gè)任務(wù)的能力,不一定要同時(shí)。
線程: 線程本質(zhì)上是進(jìn)程中一段并發(fā)運(yùn)行的代碼,所以線程需要操作系統(tǒng)投入CPU資源來運(yùn)行和調(diào)度。
線程都擁有各自的計(jì)數(shù)器、堆棧和局部變量等屬性,并且能夠訪問共享的內(nèi)存變量。一個(gè)線程在一個(gè)時(shí)刻只能運(yùn)行在一個(gè)處理器核心上。
多線程中每個(gè)線程的處理程序依然是順序執(zhí)行。多線程可以實(shí)現(xiàn)線程間的切換執(zhí)行。異步:異步使用回調(diào)的方式進(jìn)行處理。異步是最終目的,多線程只是我們實(shí)現(xiàn)異步的一種手段。
上下文切換:任務(wù)從保存到再加載的過程就是一次上下文切換。
參考