【Java核心基礎(chǔ)知識(shí)】04 - 多線程并發(fā)(3)

多線程知識(shí)點(diǎn)目錄

多線程并發(fā)(1)- http://www.reibang.com/p/8fcfcac74033
多線程并發(fā)(2)-http://www.reibang.com/p/a0c5095ad103
多線程并發(fā)(3)-http://www.reibang.com/p/c5c3bbd42c35
多線程并發(fā)(4)-http://www.reibang.com/p/e45807a9853e
多線程并發(fā)(5)-http://www.reibang.com/p/5217588d82ba
多線程并發(fā)(6)-http://www.reibang.com/p/d7c888a9c03c

七忽孽、Java后臺(tái)線程(守護(hù)線程)

  1. 定義:守護(hù)線程,也稱“服務(wù)線程”常挚,是一種特殊的線程,這種線程不屬于程序中不可或缺的一部分稽物,當(dāng)沒有用戶線程可服務(wù)時(shí)奄毡,后臺(tái)線程會(huì)自動(dòng)離開。

  2. 優(yōu)先級(jí):守護(hù)線程的優(yōu)先級(jí)比較低贝或,用來在后臺(tái)為系統(tǒng)中其他對(duì)象和線程提供服務(wù)吼过。

  3. 設(shè)置:通過setDaemon(true)來設(shè)置線程為“守護(hù)線程”。將一個(gè)用戶線程設(shè)置為守護(hù)線程的方式是在線程對(duì)象創(chuàng)建之前咪奖,調(diào)用線程對(duì)象的setDaemon()方法那先。

  4. 在Daemon線程中產(chǎn)生的新線程也是Daemon線程。

  5. 線程是JVM級(jí)別的赡艰,獨(dú)立于具體的Java應(yīng)用程序售淡,生命周期是由操作系統(tǒng)來管理。以Tomcat為例慷垮,它在Web應(yīng)用中啟動(dòng)的線程并不會(huì)與Web應(yīng)用保持同步的生命周期揖闸。即使你停止了Web應(yīng)用,這個(gè)線程仍然會(huì)繼續(xù)運(yùn)行料身。

  6. 守護(hù)線程示例:垃圾回收線程汤纸。當(dāng)程序中不再有任何運(yùn)行的Thread,程序就不會(huì)再產(chǎn)生垃圾芹血,垃圾回收器就無事可做贮泞,*所以當(dāng)垃圾回收線程是JVM上僅剩的線程時(shí),垃圾回收線程會(huì)自動(dòng)離開幔烛。它始終在低級(jí)別的狀態(tài)中運(yùn)行啃擦,用于實(shí)時(shí)監(jiān)控和管理系統(tǒng)中的可回收資源。

  7. 生命周期:守護(hù)進(jìn)程(Daemon)是運(yùn)行在后臺(tái)的一種特殊進(jìn)程饿悬,它不與用戶進(jìn)行交互令蛉,也不依賴于終端。守護(hù)線程不會(huì)受到用戶終端的控制狡恬,它會(huì)按照一定的周期或條件執(zhí)行特定的任務(wù)珠叔,或者等待處理某些事件。守護(hù)線程不依賴于用戶終端弟劲,但它依賴于操作系統(tǒng)祷安。當(dāng)系統(tǒng)運(yùn)行時(shí),守護(hù)線程會(huì)一直存在并執(zhí)行任務(wù)兔乞,當(dāng)系統(tǒng)關(guān)閉時(shí)汇鞭,守護(hù)線程也會(huì)終止撇眯。如果JVM中的所有線程都是守護(hù)線程,那么JVM會(huì)認(rèn)為沒有需要繼續(xù)運(yùn)行的線程虱咧,因此可以退出熊榛。但如果還有非守護(hù)線程在運(yùn)行,那么JVM會(huì)認(rèn)為還有其他工作需要完成腕巡,因此不會(huì)退出玄坦。(簡(jiǎn)單來說:守護(hù)線程是一種在后臺(tái)運(yùn)行并執(zhí)行特定任務(wù)的特殊線程。它是獨(dú)立于用戶終端的绘沉,但依賴于操作系統(tǒng)煎楣。當(dāng)系統(tǒng)中沒有非守護(hù)線程時(shí),JVM會(huì)選擇退出)

八车伞、JAVA鎖

8.1 樂觀鎖

樂觀鎖是一種樂觀思想择懂,即認(rèn)為讀多寫少,遇到并發(fā)寫的可能性低另玖,拿取數(shù)據(jù)時(shí)認(rèn)為別人不會(huì)修改困曙,所以不上鎖,但是在更新的時(shí)候會(huì)判斷一下在次期間別人有沒有去更新這個(gè)數(shù)據(jù)谦去,采取先讀出當(dāng)前版本號(hào)慷丽,然后加鎖操作,比較跟上一次的版本號(hào)鳄哭,一樣則更新要糊,如果失敗則重讀-比較-寫操作。

Java中的樂觀鎖基本都是通過CAS操作實(shí)現(xiàn)的妆丘,CAS是一種更新的原子操作锄俄,比較當(dāng)前值跟傳入值是否相同,同則更新勺拣,否則失敗奶赠。

8.2 悲觀鎖

悲觀鎖是一種悲觀思想,即認(rèn)為寫多宣脉,遇到并發(fā)寫的可能性高车柠,拿取數(shù)據(jù)時(shí)認(rèn)為別人會(huì)修改剔氏,所以每次在讀寫數(shù)據(jù)的時(shí)候都會(huì)上鎖塑猖,這樣別人想讀寫這個(gè)數(shù)據(jù)就會(huì)block直到拿到鎖。

Java中的悲觀鎖就是Synchronized谈跛,AQS框架下的鎖則是先嘗試CAS樂觀鎖去獲取鎖羊苟,獲取不到才會(huì)轉(zhuǎn)換為悲觀鎖,如RetreenLock感憾。

8.3 自旋鎖

自旋鎖原理:如果持有鎖的線程能再很短時(shí)間內(nèi)釋放鎖資源蜡励,那么那些等待競(jìng)爭(zhēng)鎖的線程就不需要做內(nèi)核態(tài)和用戶態(tài)之間的切換進(jìn)入阻塞掛起狀態(tài),它們只需要等一等(自旋),等待有鎖的線程釋放鎖后立即獲取凉倚,就避免用戶線程和內(nèi)核的切換的消耗兼都。

線程自旋是需要消耗CPU的,如果一直獲取不到鎖稽寒,那線程也不能一直占用CPU自旋做無用功扮碧,所以需要設(shè)定一個(gè)自旋等待的最大時(shí)間。

如果持有鎖的線程執(zhí)行的時(shí)間超過自旋等待的最大時(shí)間仍沒有釋放鎖杏糙,則會(huì)導(dǎo)致其它爭(zhēng)用鎖的線程在最大等待時(shí)間內(nèi)還是獲取不到鎖慎王,這時(shí)爭(zhēng)用線程會(huì)停止自旋,進(jìn)入阻塞狀態(tài)宏侍。

8.4 Synchronized同步鎖

synchronized可以把任意一個(gè)非NULL的對(duì)象當(dāng)作鎖赖淤。它屬于獨(dú)占式的悲觀鎖,同時(shí)屬于可重入鎖谅河。

synchronized作用范圍

  1. 作用于方法時(shí)咱旱,鎖住的是對(duì)象的實(shí)例(this)
  2. 作用于靜態(tài)方法時(shí),鎖住的是Class實(shí)例绷耍,又因?yàn)镃lass的相關(guān)數(shù)據(jù)存儲(chǔ)在永久帶PermGen(JDK1.8則是metaspace)莽龟,永久帶是全局共享的,因此靜態(tài)方法鎖相當(dāng)于類的一個(gè)全局鎖锨天,會(huì)鎖所有調(diào)用該方法的線程
  3. 作用于一個(gè)對(duì)象實(shí)例時(shí)毯盈,鎖住的是所有以該對(duì)象為鎖的代碼塊。它有過個(gè)隊(duì)列病袄,當(dāng)多個(gè)線程一起訪問某個(gè)對(duì)象監(jiān)視器時(shí)搂赋,對(duì)象監(jiān)視器會(huì)將這些線程存儲(chǔ)在不同的容器中。

synchronized核心組件

  1. Wait Set(等待集合):那些調(diào)用wait方法被阻塞的線程被放置在這里
  2. Contention List(鎖競(jìng)爭(zhēng)隊(duì)列):競(jìng)爭(zhēng)隊(duì)列益缠,所有請(qǐng)求鎖的線程首先被放在這個(gè)競(jìng)爭(zhēng)隊(duì)列中
  3. Entry List(競(jìng)爭(zhēng)候選列表):Contention List中那些有資格成為候選資源的線程被移動(dòng)到Entry List中
  4. OnDeck(待處理隊(duì)列):任意時(shí)刻脑奠,最多只有一個(gè)線程正在競(jìng)爭(zhēng)鎖資源,該線程被稱為OnDeck
  5. Owner(持鎖狀態(tài)):當(dāng)前已經(jīng)獲取到所有資源的線程稱為Owner
  6. !Owner:當(dāng)前釋放鎖的線程

synchronized實(shí)現(xiàn)機(jī)制

synchronized實(shí)現(xiàn)機(jī)制

8.5 ReentrantLock

ReentrantLock繼承接口Lock并實(shí)現(xiàn)了接口中定義的方法幅慌,他是一種可重入鎖宋欺,除了能完成synchronized所能完成的所有工作外,還提供了諸如可響應(yīng)中斷鎖胰伍、可輪詢鎖請(qǐng)求齿诞、定時(shí)鎖等避免多線程死鎖的方法。

ReentrantLock特性
  • 可重入:意味著一個(gè)線程可以多次獲取同一個(gè)鎖骂租,而不會(huì)產(chǎn)生死鎖祷杈。

  • 公平鎖:ReentrantLock 可以配置為公平鎖和非公平鎖。公平鎖按照線程請(qǐng)求鎖的順序來分配鎖渗饮,而非公平鎖則沒有這個(gè)限制但汞。

  • 可中斷:當(dāng)一個(gè)線程持有鎖時(shí)宿刮,其他線程可以嘗試獲取鎖,如果獲取失敗私蕾,那么這個(gè)線程可以選擇中斷等待的線程僵缺。

  • 可嘗試:可以嘗試獲取鎖,而不會(huì)阻塞當(dāng)前線程踩叭。

ReentrantLock使用
import java.util.concurrent.locks.ReentrantLock;  
  
public class ReentrantLockExample {  

    private final ReentrantLock lock = new ReentrantLock();  
  
    public void accessResource() {  
        // 獲取鎖
        lock.lock();  // block until condition holds  
        try {  
            // ... method body  
        } finally {  
            // 釋放鎖
            lock.unlock()  
        }  
    }  
}
公平鎖 & 非公平鎖

公平鎖:通常先對(duì)鎖提出獲取請(qǐng)求的線程會(huì)先被分配到鎖谤饭。
非公平鎖:JVM按隨機(jī)、就近原則分配鎖的機(jī)制懊纳。

效率:非公平鎖執(zhí)行的效率要遠(yuǎn)遠(yuǎn)超出公平鎖揉抵,除非程序有特殊需求,否則最常用非公平鎖嗤疯。

可以通過在創(chuàng)建 ReentrantLock 時(shí)設(shè)置參數(shù)來選擇使用公平鎖還是非公平鎖冤今,默認(rèn)為非公平鎖。

// 公平鎖  -  鎖會(huì)盡可能地按照線程請(qǐng)求的順序分配
ReentrantLock fairLock = new ReentrantLock(true);  
  
// 非公平鎖  
ReentrantLock unfairLock = new ReentrantLock(false);
ReentrantLock 與 Synchronized
  1. ReentrantLock通過方法lock()與unlock()來進(jìn)行加鎖與解鎖操作茂缚,與Synchronized會(huì)被JVM自動(dòng)解鎖機(jī)制不同戏罢,ReentrantLock加鎖后需要手動(dòng)進(jìn)行解鎖。為了避免程序出現(xiàn)異常而無法正常解鎖的情況脚囊,使用ReentrantLock必須在finally控制塊中進(jìn)行解鎖操作龟糕。
  2. ReentrantLock相比Synchronized的優(yōu)勢(shì)是可中斷、公平鎖悔耘、多個(gè)鎖讲岁。這種情況下需要使用ReentrantLock。

8.6 Senaphore信號(hào)量

Semaphore是一種基于計(jì)數(shù)的信號(hào)量衬以。它可以設(shè)定一個(gè)閥值缓艳,基于此,多個(gè)線程競(jìng)爭(zhēng)獲取許可信號(hào)看峻,做完自己的申請(qǐng)后歸還阶淘,超過閥值后,線程申請(qǐng)?jiān)S可信號(hào)將會(huì)被阻塞互妓。Semaphore可用來構(gòu)建一些對(duì)象池溪窒、資源池之類的,比如數(shù)據(jù)庫(kù)連接池冯勉。

實(shí)現(xiàn)互斥鎖(計(jì)數(shù)器為1):創(chuàng)建計(jì)數(shù)為1的Semaphore澈蚌,將其作為一種類似互斥鎖的機(jī)制,這也叫二元信號(hào)量珠闰,表示兩種互斥狀態(tài)惜浅。

import java.util.concurrent.Semaphore;  
  
public class SemaphoreExample {  
    private static Semaphore semaphore = new Semaphore(3); // 允許3個(gè)線程同時(shí)訪問共享資源  
  
    public static void main(String[] args) {  
        for (int i = 0; i < 5; i++) {  
            new Thread(() -> {  
                try {  
                    semaphore.acquire(); // 獲取一個(gè)許可證,如果沒有伏嗜,線程將阻塞直到有一個(gè)可用  
                    System.out.println("Thread " + Thread.currentThread().getId() + " is accessing the resource.");  
                    Thread.sleep(1000); // 模擬資源訪問時(shí)間  
                    System.out.println("Thread " + Thread.currentThread().getId() + " finished accessing the resource.");  
                    semaphore.release(); // 釋放許可證坛悉,允許其他線程獲取許可證并訪問資源  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }).start();  
        }  
    }  
}

在這個(gè)例子中,我們創(chuàng)建了一個(gè)信號(hào)量 semaphore承绸,初始化了3個(gè)許可證裸影。然后我們創(chuàng)建了5個(gè)線程,每個(gè)線程都會(huì)嘗試獲取許可證來訪問共享資源军熏。如果當(dāng)前沒有可用的許可證轩猩,線程將會(huì)被阻塞直到有一個(gè)可用。當(dāng)線程訪問完共享資源后荡澎,它會(huì)釋放一個(gè)許可證均践,這樣其他線程就可以獲取許可證并訪問資源。

SemaphoreReentrantLock

Semaphore 基本能完成 ReentrantLock 的所有工作摩幔,使用方法也類似彤委,通過acquire()與release()方法來獲得和釋放臨界資源。

經(jīng)實(shí)測(cè)或衡,Semaphore.acquire()方法默認(rèn)為可響應(yīng)中斷鎖焦影,與ReentrantLock.lockInterruptibly()作用效果一致,也就是說在等待臨界資源的過程中可以被Thread.interrupt()方法中斷封断。

此外斯辰,Semaphore也實(shí)現(xiàn)了可輪詢的鎖請(qǐng)求與定時(shí)鎖的功能,除了方法名TryAcquire與tryLock不同坡疼,其使用方法與ReentrantLock幾乎一致彬呻。Semaphore也提供了公平與非公平鎖的機(jī)制,也可在構(gòu)造函數(shù)中進(jìn)行設(shè)定柄瑰。

Semaphore 的鎖釋放操作也由手動(dòng)進(jìn)行废岂,因此與 ReentrantLock 一樣,為避免線程因拋出異常而無法正常釋放鎖的情況發(fā)生狱意,釋放鎖的操作也必須在 finally 代碼塊中完成湖苞。

8.7 AtomicInteger

AtomicInteger是一個(gè)提供原子操作的Integer的類,常見的還有AtomicBoolean详囤、AtomicLong财骨、AtomicReference等,他們的實(shí)現(xiàn)原理相同藏姐,區(qū)別在與運(yùn)算對(duì)象類型不同隆箩。還可以通過AtomicReference<T>將一個(gè)對(duì)象的所有操作轉(zhuǎn)化成原子操作。
在多線程程序中羔杨,諸如++i或i++等運(yùn)算不具有原子性捌臊,是不安全的線程操作之一。通常我們會(huì)使用Synchronized將操作變成一個(gè)原子操作兜材,但JVM為此類操作特意提供了一些同步類理澎,使得使用更方便逞力,且使程序運(yùn)行效率更高。

8.8 ReadWriteLock讀寫鎖

Java提供了讀寫鎖糠爬,在讀的地方使用讀鎖寇荧,在寫的地方使用寫鎖,靈活控制执隧。

如果沒有寫鎖的情況下揩抡,讀是無阻塞的,在一定程度上提高了程序的執(zhí)行效率镀琉。多個(gè)讀鎖不互斥峦嗤,讀鎖與寫鎖互斥,這是由JVM控制的屋摔,無需我們來控制烁设。

九、線程上下文切換

時(shí)間片輪轉(zhuǎn)(或稱為時(shí)間片調(diào)度)是一種策略凡壤,CPU 依次為每個(gè)任務(wù)提供一段時(shí)間的服務(wù)署尤,然后把當(dāng)前任務(wù)的狀態(tài)保存下來,在加載下一任務(wù)的狀態(tài)后亚侠,繼續(xù)服務(wù)下一任務(wù)曹体,任務(wù)的狀態(tài)保存及再加載, 這段過程就叫做上下文切換。時(shí)間片輪轉(zhuǎn)的方式使多個(gè)任務(wù)在同一顆 CPU 上執(zhí)行變成了可能硝烂。


線程上下文切換
1)進(jìn)程

是指一個(gè)程序運(yùn)行的實(shí)例(又稱任務(wù))箕别。在Linux系統(tǒng)中,線程就是能并行運(yùn)行并且與他們的父進(jìn)程(創(chuàng)建他們的進(jìn)程)共享同一地址空間(一段內(nèi)存區(qū)域)和其他資源的輕量級(jí)的進(jìn)程滞谢。

2)上下文

指某一時(shí)間點(diǎn)CPU寄存器和程序計(jì)數(shù)器的內(nèi)容串稀。

3)寄存器

CPU內(nèi)部的數(shù)量較少但速度很快的內(nèi)存(與之對(duì)應(yīng)的是CPU外部相對(duì)較慢的RAM主內(nèi)存)。寄存器通過對(duì)常用值的快速訪問來提高計(jì)算機(jī)程序運(yùn)行的速度狮杨。

4)程序計(jì)數(shù)器

一個(gè)專用的寄存器母截,用于表明指令序列中CPU正在執(zhí)行的位置,存的值為正在執(zhí)行的指令的位置或者下一個(gè)將要被執(zhí)行的指令的位置橄教,具體依賴于特定的系統(tǒng)清寇。

5)PCB-“切換幀”

上下文切換可以認(rèn)為是內(nèi)核在CPU上對(duì)進(jìn)程進(jìn)行切換,上下文切換過程中的信息是保存在進(jìn)程控制塊(PCB, Process Control Block)中的护蝶。PCB還經(jīng)常被稱作“切換幀”华烟。信息會(huì)一直保存到CPU的內(nèi)存中,知道他們被再次使用持灰。

6)上下文切換的活動(dòng)
  1. 掛起一個(gè)進(jìn)程盔夜,將這個(gè)進(jìn)程在CPU中的狀態(tài)(上下文)存儲(chǔ)于內(nèi)存中的某處。
  2. 在內(nèi)存中檢索下一個(gè)進(jìn)程的上下文并將其在CPU的寄存器中回復(fù)。
  3. 跳轉(zhuǎn)到程序計(jì)數(shù)器所指向的位置(即進(jìn)程被中斷時(shí)的代碼行)喂链,以恢復(fù)該進(jìn)程在程序中返十。
7)引起上下文切換的原因
  1. 當(dāng)前執(zhí)行任務(wù)的時(shí)間片用完之后,系統(tǒng)CPU正常調(diào)度下一個(gè)任務(wù)衩藤;
  2. 當(dāng)前執(zhí)行任務(wù)碰到IO阻塞吧慢,調(diào)度器將此任務(wù)掛起涛漂,繼續(xù)下一任務(wù)赏表;
  3. 多個(gè)任務(wù)搶占鎖資源,當(dāng)前任務(wù)沒有搶到鎖資源匈仗,被調(diào)度器掛起瓢剿,繼續(xù)下一任務(wù);
  4. 用戶代碼掛起當(dāng)前任務(wù)悠轩,讓出CPU時(shí)間间狂;
  5. 硬件終端。

十火架、線程池原理

線程池做的工作主要是控制運(yùn)行的線程的數(shù)量鉴象,處理過程中將任務(wù)放入隊(duì)列,然后在線程創(chuàng)建后啟動(dòng)這些任務(wù)何鸡,如果線程數(shù)量超過了最大數(shù)量超出數(shù)量的線程排隊(duì)等待纺弊,等其他線程執(zhí)行完畢,再?gòu)年?duì)列中取出任務(wù)來執(zhí)行骡男。它的主要特點(diǎn)是:線程復(fù)用淆游、控制最大并發(fā)數(shù)管理線程隔盛。

10.1 線程復(fù)用

每一個(gè)Thread的類都有一個(gè)start()方法犹菱。當(dāng)調(diào)用start()啟動(dòng)線程時(shí)Java虛擬機(jī)會(huì)調(diào)用該類的run()方法。那么該類的run()方法中就是調(diào)用了Runnable對(duì)象的run()方法吮炕。我們可以繼承重寫Thread類腊脱,再其start()方法中添加不斷循環(huán)調(diào)用傳遞過來的Runnable對(duì)象。這就是線程池的實(shí)現(xiàn)原理龙亲。循環(huán)方法中不斷獲取Runnable是用Queue實(shí)現(xiàn)的陕凹,在獲取下一個(gè)Runnable之前可以是阻塞的。

10.2 線程池的組成

  1. 線程池管理器:用于創(chuàng)建并管理線程池
  2. 工作線程:線程池中的線程
  3. 任務(wù)接口:每個(gè)任務(wù)必須實(shí)現(xiàn)的接口俱笛,用于工作線程調(diào)度其運(yùn)行
  4. 任務(wù)隊(duì)列:用于存放待處理的任務(wù)捆姜,提供一種緩沖機(jī)制

Java中的線程池是通過Executor框架實(shí)現(xiàn)的,該框架中用到了Executor迎膜、Executors泥技、ExecutorService、ThreadPoolExecutor磕仅、Callable和Future珊豹、FutureTask這幾個(gè)類簸呈。


Executor框架

10.3 拒絕策略

線程池中的線程已經(jīng)用完了,無法繼續(xù)為新任務(wù)服務(wù)店茶,同時(shí)蜕便,等待隊(duì)列也已經(jīng)排滿了,再也塞不下新任務(wù)了贩幻。這時(shí)候轿腺,我們就需要拒絕策略機(jī)制合理的處理這個(gè)問題。
JDK內(nèi)置的拒絕策略:

  1. AbortPolicy:直接拋出異常丛楚,組織系統(tǒng)正常運(yùn)行族壳。
  2. CallerRunsPolicy:只要線程池未關(guān)閉,該策略直接在調(diào)用者線程中趣些,運(yùn)行當(dāng)前被丟棄的任務(wù)仿荆。顯然這樣做不會(huì)真的丟棄任務(wù),但是坏平,任務(wù)提交線程的性能極有可能會(huì)急劇下降拢操。
  3. DiscardOldestPolicy:丟棄最老的一個(gè)請(qǐng)求,也就是即將被執(zhí)行的一個(gè)任務(wù)舶替,并嘗試再次提交當(dāng)前任務(wù)令境。
  4. DiscardPolicy:丟棄無法處理的任務(wù),不予任何處理坎穿。如果運(yùn)行任務(wù)丟失展父,這是最好的一種方案。

以上內(nèi)置拒絕策略均實(shí)現(xiàn)了RejectedExecutionHandler接口玲昧,若以上策略仍無法滿足實(shí)際需要栖茉,可拓展RejectedExecutionHandler接口。

10.4 Java線程池工作過程

  1. 線程池剛創(chuàng)建時(shí)孵延,里面沒有線程吕漂。任務(wù)隊(duì)列是作為參數(shù)傳進(jìn)來的。不過尘应,就算隊(duì)列里面有任務(wù)惶凝,線程池也不會(huì)馬上執(zhí)行它們。
  2. 當(dāng)調(diào)用execute()方法添加一個(gè)任務(wù)時(shí)犬钢,線程池會(huì)做如下判斷:
  • (1)如果正在運(yùn)行的線程數(shù)量小于corePoolSize苍鲜,那么馬上創(chuàng)建線程運(yùn)行這個(gè)任務(wù);
  • (2)如果正在運(yùn)行的線程數(shù)大于或等于corePoolSize玷犹,那么將這個(gè)任務(wù)放入隊(duì)列混滔。
  • (3)如果這時(shí)候隊(duì)列滿了,而且正在運(yùn)行的線程數(shù)量小于maximimPoolSize,那么還是要?jiǎng)?chuàng)建非核心線程立即運(yùn)行這個(gè)任務(wù)坯屿。
  • (4)如果隊(duì)列滿了油湖,而且正在運(yùn)行的線程數(shù)量大于或等于maximumPoolSize,那么線程池會(huì)拋出異常RejectExecutionExeption领跛。
  1. 當(dāng)一個(gè)線程完成任務(wù)時(shí)乏德,它會(huì)從隊(duì)列中取下一個(gè)任務(wù)來執(zhí)行。
  2. 當(dāng)一個(gè)線程無事可做吠昭,超過一定時(shí)間(KeepAliveTime)時(shí)喊括,線程池會(huì)判斷,如果當(dāng)前運(yùn)行的線程大于CorePoolSize怎诫,那么這個(gè)線程就被停掉瘾晃。所以線程池的所有任務(wù)完成后贷痪,它最終會(huì)縮到CorePoolSize的大小幻妓。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市劫拢,隨后出現(xiàn)的幾起案子肉津,更是在濱河造成了極大的恐慌,老刑警劉巖舱沧,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹沙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡熟吏,警方通過查閱死者的電腦和手機(jī)距糖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牵寺,“玉大人悍引,你說我怎么就攤上這事∶泵ィ” “怎么了趣斤?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)黎休。 經(jīng)常有香客問我浓领,道長(zhǎng),這世上最難降的妖魔是什么势腮? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任联贩,我火速辦了婚禮,結(jié)果婚禮上捎拯,老公的妹妹穿的比我還像新娘泪幌。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布座菠。 她就那樣靜靜地躺著狸眼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浴滴。 梳的紋絲不亂的頭發(fā)上拓萌,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音升略,去河邊找鬼微王。 笑死,一個(gè)胖子當(dāng)著我的面吹牛品嚣,可吹牛的內(nèi)容都是我干的炕倘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼翰撑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼罩旋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起眶诈,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤涨醋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逝撬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浴骂,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年宪潮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了溯警。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狡相,死狀恐怖梯轻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谣光,我是刑警寧澤檩淋,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站萄金,受9級(jí)特大地震影響蟀悦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氧敢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一日戈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孙乖,春花似錦浙炼、人聲如沸份氧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蜗帜。三九已至,卻和暖如春资厉,著一層夾襖步出監(jiān)牢的瞬間厅缺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工宴偿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留湘捎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓窄刘,卻偏偏與公主長(zhǎng)得像窥妇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娩践,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容