1.不要調(diào)用Thread類(lèi)或者Runnable對(duì)象的run方法趴乡。
- 直接調(diào)用run方法只會(huì)在同一個(gè)線程中執(zhí)行任務(wù),而沒(méi)有啟動(dòng)新的線程;
- 應(yīng)當(dāng)調(diào)用Thread.start方法咳蔚,這會(huì)創(chuàng)建一個(gè)新線程來(lái)執(zhí)行run方法商佑;
2.現(xiàn)在線程優(yōu)先級(jí)高度依賴系統(tǒng)锯茄。
- Java有10個(gè)線程優(yōu)先級(jí)(1~10),10最高茶没,默認(rèn)為5肌幽;
- Windows有7個(gè)優(yōu)先級(jí)別;面向Linux的Oracle JVM抓半,會(huì)完全忽略線程優(yōu)先級(jí)牍颈;
- Java線程的優(yōu)先級(jí)會(huì)映射到主機(jī)平臺(tái)優(yōu)先級(jí);
- 現(xiàn)在的Java線程優(yōu)先級(jí)設(shè)定不是很有用琅关,盡量不要使用了煮岁;
3. ReentrantLock(可重入)鎖可以反復(fù)獲取已擁有的鎖。
- 內(nèi)部持有計(jì)數(shù)器來(lái)跟蹤對(duì)lock方法的嵌套調(diào)用涣易;每一層調(diào)用都需要unlock來(lái)釋放画机;
4. 條件對(duì)象:Condition。
- 一個(gè)鎖對(duì)象可以有一個(gè)或者多個(gè)關(guān)聯(lián)的條件對(duì)象新症。
- 已獲得鎖的對(duì)象步氏,當(dāng)不滿足條件對(duì)象的條件時(shí),會(huì)暫停并釋放鎖徒爹;當(dāng)條件滿足后荚醒,又會(huì)從之前暫停的地方開(kāi)始繼續(xù)執(zhí)行;
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
while (accounts[from] < amount) { // 要用while隆嗅,因?yàn)閱拘押筮€得再次檢查條件
// sufficientFunds = bankLock.newCondition();
sufficientFunds.await();
// transfer funds ...
sufficientFunds.signalAll(); // 會(huì)激活等待這個(gè)條件的所有線程
}
}
}
- 只有當(dāng)線程擁有一個(gè)條件的鎖時(shí)界阁,才能在這個(gè)條件上調(diào)用await、signalAll或者signal方法胖喳;
5. synchronized 關(guān)鍵字(內(nèi)部對(duì)象鎖)泡躯;
- 每個(gè)Java對(duì)象都有一個(gè)內(nèi)部鎖;如果在一個(gè)方法上使用synchronized關(guān)鍵字丽焊,調(diào)用這個(gè)方法時(shí)较剃,線程必須獲得內(nèi)部對(duì)象鎖;
- 每個(gè)內(nèi)部對(duì)象鎖只有一個(gè)關(guān)聯(lián)條件技健;
- 最好既不使用Lock/Condition写穴,也不使用synchronized關(guān)鍵字,可以使用java.util.concurrent包的某些機(jī)制(比如阻塞隊(duì)列)來(lái)更好的完成并發(fā)處理雌贱;
6. volatile字段
如果為了能并發(fā)讀寫(xiě)一兩個(gè)實(shí)例字段啊送,可以不使用鎖偿短,而是使用volatile字段實(shí)現(xiàn);
- 標(biāo)記為volatile的字段删掀,編譯器和虛擬機(jī)就會(huì)考慮到該字段可能被另一個(gè)線程更新翔冀;
- 標(biāo)記為volatile的字段,每次被某一線程修改時(shí)披泪,最新值都會(huì)對(duì)所有線程可見(jiàn)纤子;
- volatile變量不能提供原子性;
// 無(wú)法保證讀取款票、取反和寫(xiě)入操作不被中斷控硼;
public void flipDone() { done = !done; } // not atomic
7. stop和suspend方法已經(jīng)廢棄,不要使用艾少;
- stop方法可能會(huì)讓對(duì)象被破壞卡乾,即未完成完整操作就被終止了;
- suspend方法會(huì)掛起持有鎖的線程缚够,導(dǎo)致線程恢復(fù)前鎖是不可用的幔妨;如果調(diào)用suspend方法的線程試圖獲取同一個(gè)鎖,程序就會(huì)死鎖谍椅;
8. 非線程安全的類(lèi)可以通過(guò)ThreadLocal包裝误堡,來(lái)讓各個(gè)線程獨(dú)立訪問(wèn);
public static final ThreadLocal<SimpleDateFormat> dateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
String dateStamp = dateFormat.get().format(new Date);