---
title: Javaå¹¶å常è§é¢è¯é¢æ»ç»
description: Javaå¹¶åç¼ç¨æ ¸å¿ç¥è¯ç¹ä¸é«é¢é¢è¯é¢æ»ç»ï¼æ¶µç线ç¨ä¸è¿ç¨ãå¹¶åä¸å¹¶è¡ã线ç¨çå½å¨æãæ»éãsynchronizedãReentrantLockãvolatileãThreadLocalãçº¿ç¨æ± ãCASãAQSçéè¦æ¦å¿µä¸å®æåºç¨ã
category: Java
tag:
- Javaå¹¶å
head:
- - meta
- name: keywords
content: Javaå¹¶åé¢è¯é¢,线ç¨åè¿ç¨,å¹¶ååå¹¶è¡,å¤çº¿ç¨,æ»é,线ç¨çå½å¨æ,synchronized,ReentrantLock,volatile,ThreadLocal,çº¿ç¨æ± ,CAS,AQS,å¹¶åç¼ç¨,éæºå¶
---
è¿é¨åå
容æèª [JavaGuide](https://javaguide.cn/) ä¸é¢å ç¯æç« ä¸çéç¹ï¼
- [Javaå¹¶å常è§é¢è¯é¢æ»ç»ï¼ä¸ï¼](https://javaguide.cn/java/concurrent/java-concurrent-questions-01.html)ï¼å¤çº¿ç¨åºç¡ç¥è¯ï¼ä¾å¦çº¿ç¨åè¿ç¨çæ¦å¿µãæ»éï¼
- [Javaå¹¶å常è§é¢è¯é¢æ»ç»ï¼ä¸ï¼](https://javaguide.cn/java/concurrent/java-concurrent-questions-02.html)ï¼åç§éï¼ä¾å¦ä¹è§éåæ²è§éã`synchronized`å
³é®åã`ReentrantLock`ï¼
- [Javaå¹¶å常è§é¢è¯é¢æ»ç»ï¼ä¸ï¼](https://javaguide.cn/java/concurrent/java-concurrent-questions-03.html)(`ThreadLocal`ãçº¿ç¨æ± ã`Future`ãAQSãèæçº¿ç¨ç)
## 线ç¨
### âï¸ä»ä¹æ¯çº¿ç¨åè¿ç¨?
#### ä½ä¸ºè¿ç¨?
è¿ç¨æ¯ç¨åºç䏿¬¡æ§è¡è¿ç¨ï¼æ¯ç³»ç»è¿è¡ç¨åºçåºæ¬åä½ï¼å æ¤è¿ç¨æ¯å¨æçãç³»ç»è¿è¡ä¸ä¸ªç¨åºå³æ¯ä¸ä¸ªè¿ç¨ä»å建ï¼è¿è¡å°æ¶äº¡çè¿ç¨ã
å¨ Java ä¸ï¼å½æä»¬å¯å¨ main 彿°æ¶å
¶å®å°±æ¯å¯å¨äºä¸ä¸ª JVM çè¿ç¨ï¼è main 彿°æå¨ç线ç¨å°±æ¯è¿ä¸ªè¿ç¨ä¸çä¸ä¸ªçº¿ç¨ï¼ä¹ç§°ä¸»çº¿ç¨ã
å¦ä¸å¾æç¤ºï¼å¨ Windows ä¸éè¿æ¥çä»»å¡ç®¡çå¨çæ¹å¼ï¼æä»¬å°±å¯ä»¥æ¸
æ¥çå° Windows å½åè¿è¡çè¿ç¨ï¼`.exe` æä»¶çè¿è¡ï¼ã

#### ä½ä¸ºçº¿ç¨?
线ç¨ä¸è¿ç¨ç¸ä¼¼ï¼ä½çº¿ç¨æ¯ä¸ä¸ªæ¯è¿ç¨æ´å°çæ§è¡åä½ãä¸ä¸ªè¿ç¨å¨å
¶æ§è¡çè¿ç¨ä¸å¯ä»¥äº§çå¤ä¸ªçº¿ç¨ãä¸è¿ç¨ä¸åçæ¯åç±»çå¤ä¸ªçº¿ç¨å
±äº«è¿ç¨ç**å **å**æ¹æ³åº**èµæºï¼ä½æ¯ä¸ªçº¿ç¨æèªå·±ç**ç¨åºè®¡æ°å¨**ã**èææºæ **å**æ¬å°æ¹æ³æ **ï¼æä»¥ç³»ç»å¨äº§çä¸ä¸ªçº¿ç¨ï¼ææ¯å¨å个线ç¨ä¹é´å忢工使¶ï¼è´æ
è¦æ¯è¿ç¨å°å¾å¤ï¼ä¹æ£å ä¸ºå¦æ¤ï¼çº¿ç¨ä¹è¢«ç§°ä¸ºè½»é级è¿ç¨ã
Java ç¨åºå¤©çå°±æ¯å¤çº¿ç¨ç¨åºï¼æä»¬å¯ä»¥éè¿ JMX æ¥ççä¸ä¸ªæ®éç Java ç¨åºæåªäºçº¿ç¨ï¼ä»£ç å¦ä¸ã
```java
public class MultiThread {
public static void main(String[] args) {
// è·å Java 线ç¨ç®¡ç MXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// ä¸éè¦è·å忥ç monitor å synchronizer ä¿¡æ¯ï¼ä»
è·å线ç¨å线ç¨å æ ä¿¡æ¯
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
// éå线ç¨ä¿¡æ¯ï¼ä»
æå°çº¿ç¨ ID å线ç¨åç§°ä¿¡æ¯
for (ThreadInfo threadInfo : threadInfos) {
System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
}
}
}
```
ä¸è¿°ç¨åºè¾åºå¦ä¸ï¼è¾åºå
容å¯è½ä¸åï¼ä¸ç¨å¤ªçº ç»ä¸é¢æ¯ä¸ªçº¿ç¨çä½ç¨ï¼åªç¨ç¥é main çº¿ç¨æ§è¡ main æ¹æ³å³å¯ï¼ï¼
```plain
[5] Attach Listener //æ·»å äºä»¶
[4] Signal Dispatcher // ååå¤çç» JVM ä¿¡å·ç线ç¨
[3] Finalizer //è°ç¨å¯¹è±¡ finalize æ¹æ³ç线ç¨
[2] Reference Handler //æ¸
é¤ reference 线ç¨
[1] main //main 线ç¨,ç¨åºå
¥å£
```
ä»ä¸é¢çè¾åºå
容å¯ä»¥çåºï¼**ä¸ä¸ª Java ç¨åºçè¿è¡æ¯ main 线ç¨åå¤ä¸ªå
¶ä»çº¿ç¨åæ¶è¿è¡**ã
### Java 线ç¨åæä½ç³»ç»ççº¿ç¨æå¥åºå«ï¼
JDK 1.2 ä¹åï¼Java çº¿ç¨æ¯åºäºç»¿è²çº¿ç¨ï¼Green Threadsï¼å®ç°çï¼è¿æ¯ä¸ç§ç¨æ·çº§çº¿ç¨ï¼ç¨æ·çº¿ç¨ï¼ï¼ä¹å°±æ¯è¯´ JVM èªå·±æ¨¡æäºå¤çº¿ç¨çè¿è¡ï¼èä¸ä¾èµäºæä½ç³»ç»ãç±äºç»¿è²çº¿ç¨ååççº¿ç¨æ¯èµ·æ¥å¨ä½¿ç¨æ¶æä¸äºéå¶ï¼æ¯å¦ç»¿è²çº¿ç¨ä¸è½ç´æ¥ä½¿ç¨æä½ç³»ç»æä¾çåè½å¦å¼æ¥ I/Oãåªè½å¨ä¸ä¸ªå
æ ¸çº¿ç¨ä¸è¿è¡æ æ³å©ç¨å¤æ ¸ï¼ï¼å¨ JDK 1.2 å以åï¼Java çº¿ç¨æ¹ä¸ºåºäºåç线ç¨ï¼Native Threadsï¼å®ç°ï¼ä¹å°±æ¯è¯´ JVM ç´æ¥ä½¿ç¨æä½ç³»ç»åççå
æ ¸çº§çº¿ç¨ï¼å
æ ¸çº¿ç¨ï¼æ¥å®ç° Java 线ç¨ï¼ç±æä½ç³»ç»å
æ ¸è¿è¡çº¿ç¨çè°åº¦å管çã
æä»¬ä¸é¢æå°äºç¨æ·çº¿ç¨åå
æ ¸çº¿ç¨ï¼èèå°å¾å¤è¯»è
ä¸å¤ªäºè§£äºè
çåºå«ï¼è¿éç®åä»ç»ä¸ä¸ï¼
- ç¨æ·çº¿ç¨ï¼ç±ç¨æ·ç©ºé´ç¨åºç®¡çåè°åº¦ç线ç¨ï¼è¿è¡å¨ç¨æ·ç©ºé´ï¼ä¸é¨ç»åºç¨ç¨åºä½¿ç¨ï¼ã
- å
æ ¸çº¿ç¨ï¼ç±æä½ç³»ç»å
æ ¸ç®¡çåè°åº¦ç线ç¨ï¼è¿è¡å¨å
æ ¸ç©ºé´ï¼åªæå
æ ¸ç¨åºå¯ä»¥è®¿é®ï¼ã
顺便ç®åæ»ç»ä¸ä¸ç¨æ·çº¿ç¨åå
æ ¸çº¿ç¨çåºå«åç¹ç¹ï¼ç¨æ·çº¿ç¨å建ååæ¢ææ¬ä½ï¼ä½ä¸å¯ä»¥å©ç¨å¤æ ¸ãå
æ ¸æçº¿ç¨ï¼å建ååæ¢ææ¬é«ï¼å¯ä»¥å©ç¨å¤æ ¸ã
ä¸å¥è¯æ¦æ¬ Java 线ç¨åæä½ç³»ç»çº¿ç¨çå
³ç³»ï¼**ç°å¨ç Java 线ç¨çæ¬è´¨å
¶å®å°±æ¯æä½ç³»ç»ç线ç¨**ã
çº¿ç¨æ¨¡åæ¯ç¨æ·çº¿ç¨åå
æ ¸çº¿ç¨ä¹é´çå
³èæ¹å¼ï¼å¸¸è§ççº¿ç¨æ¨¡åæè¿ä¸ç§ï¼
1. ä¸å¯¹ä¸ï¼ä¸ä¸ªç¨æ·çº¿ç¨å¯¹åºä¸ä¸ªå
æ ¸çº¿ç¨ï¼
2. å¤å¯¹ä¸ï¼å¤ä¸ªç¨æ·çº¿ç¨æ å°å°ä¸ä¸ªå
æ ¸çº¿ç¨ï¼
3. å¤å¯¹å¤ï¼å¤ä¸ªç¨æ·çº¿ç¨æ å°å°å¤ä¸ªå
æ ¸çº¿ç¨ï¼

å¨ Windows å Linux çä¸»æµæä½ç³»ç»ä¸ï¼Java 线ç¨éç¨çæ¯ä¸å¯¹ä¸ççº¿ç¨æ¨¡åï¼ä¹å°±æ¯ä¸ä¸ª Java 线ç¨å¯¹åºä¸ä¸ªç³»ç»å
æ ¸çº¿ç¨ãSolaris ç³»ç»æ¯ä¸ä¸ªç¹ä¾ï¼Solaris ç³»ç»æ¬èº«å°±æ¯æå¤å¯¹å¤ççº¿ç¨æ¨¡åï¼ï¼HotSpot VM å¨ Solaris 䏿¯æå¤å¯¹å¤åä¸å¯¹ä¸ãå
·ä½å¯ä»¥åè R 大çåç: [JVM ä¸ççº¿ç¨æ¨¡åæ¯ç¨æ·çº§çä¹ï¼](https://www.zhihu.com/question/23096638/answer/29617153)ã
### âï¸è¯·ç®è¦æè¿°çº¿ç¨ä¸è¿ç¨çå
³ç³»,åºå«åä¼ç¼ºç¹ï¼
ä¸å¾æ¯ Java å
ååºåï¼éè¿ä¸å¾æä»¬ä» JVM çè§åº¦æ¥è¯´ä¸ä¸çº¿ç¨åè¿ç¨ä¹é´çå
³ç³»ã

ä»ä¸å¾å¯ä»¥çåºï¼ä¸ä¸ªè¿ç¨ä¸å¯ä»¥æå¤ä¸ªçº¿ç¨ï¼å¤ä¸ªçº¿ç¨å
±äº«è¿ç¨ç**å **å**æ¹æ³åº (JDK1.8 ä¹åçå
空é´)**èµæºï¼ä½æ¯æ¯ä¸ªçº¿ç¨æèªå·±ç**ç¨åºè®¡æ°å¨**ã**èææºæ ** å **æ¬å°æ¹æ³æ **ã
**æ»ç»ï¼** çº¿ç¨æ¯è¿ç¨ååæçæ´å°çè¿è¡åä½ã线ç¨åè¿ç¨æå¤§çä¸åå¨äºåºæ¬ä¸åè¿ç¨æ¯ç¬ç«çï¼èå线ç¨åä¸ä¸å®ï¼å 为åä¸è¿ç¨ä¸ççº¿ç¨ææå¯è½ä¼ç¸äºå½±åãçº¿ç¨æ§è¡å¼éå°ï¼ä½ä¸å©äºèµæºç管çåä¿æ¤ï¼èè¿ç¨æ£ç¸åã
### å¦ä½å建线ç¨ï¼
ä¸è¬æ¥è¯´ï¼åå»ºçº¿ç¨æå¾å¤ç§æ¹å¼ï¼ä¾å¦ç»§æ¿`Thread`ç±»ãå®ç°`Runnable`æ¥å£ãå®ç°`Callable`æ¥å£ã使ç¨çº¿ç¨æ± ã使ç¨`CompletableFuture`ç±»ççã
ä¸è¿ï¼è¿äºæ¹å¼å
¶å®å¹¶æ²¡æçæ£å建åºçº¿ç¨ãåç¡®ç¹æ¥è¯´ï¼è¿äºé½å±äºæ¯å¨ Java 代ç ä¸ä½¿ç¨å¤çº¿ç¨çæ¹æ³ã
ä¸¥æ ¼æ¥è¯´ï¼Java å°±åªæä¸ç§æ¹å¼å¯ä»¥å建线ç¨ï¼é£å°±æ¯éè¿`new Thread().start()`å建ãä¸ç®¡æ¯åªç§æ¹å¼ï¼æç»è¿æ¯ä¾èµäº`new Thread().start()`ã
å
³äºè¿ä¸ªé®é¢ç详ç»åæå¯ä»¥æ¥çè¿ç¯æç« ï¼[大家é½è¯´ Java æä¸ç§å建线ç¨çæ¹å¼ï¼å¹¶åç¼ç¨ä¸çæå¤©éªå±ï¼](https://mp.weixin.qq.com/s/NspUsyhEmKnJ-4OprRFp9g)ã
### âï¸è¯´è¯´çº¿ç¨ççå½å¨æåç¶æ?
Java 线ç¨å¨è¿è¡ççå½å¨æä¸çæå®æ¶å»åªå¯è½å¤äºä¸é¢ 6 ç§ä¸åç¶æçå
¶ä¸ä¸ä¸ªç¶æï¼
- NEW: åå§ç¶æï¼çº¿ç¨è¢«åå»ºåºæ¥ä½æ²¡æè¢«è°ç¨ `start()` ã
- RUNNABLE: è¿è¡ç¶æï¼çº¿ç¨è¢«è°ç¨äº `start()`çå¾
è¿è¡çç¶æã
- BLOCKEDï¼é»å¡ç¶æï¼éè¦çå¾
ééæ¾ã
- WAITINGï¼çå¾
ç¶æï¼è¡¨ç¤ºè¯¥çº¿ç¨éè¦çå¾
å
¶ä»çº¿ç¨ååºä¸äºç¹å®å¨ä½ï¼éç¥æä¸æï¼ã
- TIME_WAITINGï¼è¶
æ¶çå¾
ç¶æï¼å¯ä»¥å¨æå®çæ¶é´åèªè¡è¿åè䏿¯å WAITING 飿 ·ä¸ç´çå¾
ã
- TERMINATEDï¼ç»æ¢ç¶æï¼è¡¨ç¤ºè¯¥çº¿ç¨å·²ç»è¿è¡å®æ¯ã
线ç¨å¨çå½å¨æä¸å¹¶ä¸æ¯åºå®å¤äºæä¸ä¸ªç¶æèæ¯éç代ç çæ§è¡å¨ä¸åç¶æä¹é´åæ¢ã
Java 线ç¨ç¶æåè¿å¾(徿ºï¼[æé |ãJava å¹¶åç¼ç¨çèºæ¯ãä¸å
³äºçº¿ç¨ç¶æçä¸å¤é误](https://mp.weixin.qq.com/s/0UTyrJpRKaKhkhHcQtXAiA))ï¼

ç±ä¸å¾å¯ä»¥çåºï¼çº¿ç¨å建ä¹åå®å°å¤äº **NEWï¼æ°å»ºï¼** ç¶æï¼è°ç¨ `start()` æ¹æ³åå¼å§è¿è¡ï¼çº¿ç¨è¿æ¶åå¤äº **READYï¼å¯è¿è¡ï¼** ç¶æãå¯è¿è¡ç¶æç线ç¨è·å¾äº CPU æ¶é´çï¼timesliceï¼åå°±å¤äº **RUNNINGï¼è¿è¡ï¼** ç¶æã
> 卿ä½ç³»ç»å±é¢ï¼çº¿ç¨æ READY å RUNNING ç¶æï¼èå¨ JVM å±é¢ï¼åªè½çå° RUNNABLE ç¶æï¼å¾æºï¼[HowToDoInJava](https://howtodoinJava.com/ "HowToDoInJava")ï¼[Java Thread Life Cycle and Thread States](https://howtodoinJava.com/Java/multi-threading/Java-thread-life-cycle-and-thread-states/ "Java Thread Life Cycle and Thread States")ï¼ï¼æä»¥ Java ç³»ç»ä¸è¬å°è¿ä¸¤ä¸ªç¶æç»ç§°ä¸º **RUNNABLEï¼è¿è¡ä¸ï¼** ç¶æ ã
>
> **为ä»ä¹ JVM 没æåºåè¿ä¸¤ç§ç¶æå¢ï¼** ï¼æèªï¼[Java 线ç¨è¿è¡æä¹æç¬¬å
ç§ç¶æï¼ - Dawell çåç](https://www.zhihu.com/question/56494969/answer/154053599) ï¼ ç°å¨çæ¶åï¼time-sharingï¼å¤ä»»å¡ï¼multi-taskï¼æä½ç³»ç»æ¶æé叏齿¯ç¨æè°çâæ¶é´åçï¼time quantum or time sliceï¼âæ¹å¼è¿è¡æ¢å å¼ï¼preemptiveï¼è½®è½¬è°åº¦ï¼round-robin å¼ï¼ãè¿ä¸ªæ¶é´åçé常æ¯å¾å°çï¼ä¸ä¸ªçº¿ç¨ä¸æ¬¡æå¤åªè½å¨ CPU ä¸è¿è¡æ¯å¦ 10-20ms çæ¶é´ï¼æ¤æ¶å¤äº running ç¶æï¼ï¼ä¹å³å¤§æ¦åªæ 0.01 ç§è¿ä¸éçº§ï¼æ¶é´çç¨åå°±è¦è¢«åæ¢ä¸æ¥æ¾å
¥è°åº¦éåçæ«å°¾çå¾
忬¡è°åº¦ãï¼ä¹å³åå° ready ç¶æï¼ã线ç¨åæ¢ç妿¤ä¹å¿«ï¼åºåè¿ä¸¤ç§ç¶æå°±æ²¡ä»ä¹æä¹äºã

- å½çº¿ç¨æ§è¡ `wait()`æ¹æ³ä¹åï¼çº¿ç¨è¿å
¥ **WAITINGï¼çå¾
ï¼** ç¶æãè¿å
¥çå¾
ç¶æç线ç¨éè¦ä¾é å
¶ä»çº¿ç¨çéç¥æè½å¤è¿åå°è¿è¡ç¶æã
- **TIMED_WAITING(è¶
æ¶çå¾
)** ç¶æç¸å½äºå¨çå¾
ç¶æçåºç¡ä¸å¢å äºè¶
æ¶éå¶ï¼æ¯å¦éè¿ `sleepï¼long millisï¼`æ¹æ³æ `waitï¼long millisï¼`æ¹æ³å¯ä»¥å°çº¿ç¨ç½®äº TIMED_WAITING ç¶æãå½è¶
æ¶æ¶é´ç»æåï¼çº¿ç¨å°ä¼è¿åå° RUNNABLE ç¶æã
- å½çº¿ç¨è¿å
¥ `synchronized` æ¹æ³/åæè
è°ç¨ `wait` åï¼è¢« `notify`ï¼éæ°è¿å
¥ `synchronized` æ¹æ³/åï¼ä½æ¯é被å
¶å®çº¿ç¨å æï¼è¿ä¸ªæ¶å线ç¨å°±ä¼è¿å
¥ **BLOCKEDï¼é»å¡ï¼** ç¶æã
- 线ç¨å¨æ§è¡å®äº `run()`æ¹æ³ä¹åå°ä¼è¿å
¥å° **TERMINATEDï¼ç»æ¢ï¼** ç¶æã
### ä»ä¹æ¯çº¿ç¨ä¸ä¸æåæ¢?
线ç¨å¨æ§è¡è¿ç¨ä¸ä¼æèªå·±çè¿è¡æ¡ä»¶åç¶æï¼ä¹ç§°ä¸ä¸æï¼ï¼æ¯å¦ä¸ææè¯´å°è¿çç¨åºè®¡æ°å¨ï¼æ ä¿¡æ¯çãå½åºç°å¦ä¸æ
åµçæ¶åï¼çº¿ç¨ä¼ä»å ç¨ CPU ç¶æä¸éåºã
- 主å¨è®©åº CPUï¼æ¯å¦è°ç¨äº `sleep()`, `wait()` çã
- æ¶é´çç¨å®ï¼å 为æä½ç³»ç»è¦é²æ¢ä¸ä¸ªçº¿ç¨æè
è¿ç¨é¿æ¶é´å ç¨ CPU 导è´å
¶ä»çº¿ç¨æè
è¿ç¨é¥¿æ»ã
- è°ç¨äºé»å¡ç±»åçç³»ç»ä¸æï¼æ¯å¦è¯·æ± IOï¼çº¿ç¨è¢«é»å¡ã
- è¢«ç»æ¢æç»æè¿è¡
è¿å
¶ä¸åä¸ç§é½ä¼åç线ç¨åæ¢ï¼çº¿ç¨åæ¢æå³çéè¦ä¿åå½å线ç¨çä¸ä¸æï¼çå¾
线ç¨ä¸æ¬¡å ç¨ CPU çæ¶åæ¢å¤ç°åºãå¹¶å è½½ä¸ä¸ä¸ªå°è¦å ç¨ CPU ç线ç¨ä¸ä¸æãè¿å°±æ¯æè°ç **ä¸ä¸æåæ¢**ã
ä¸ä¸æåæ¢æ¯ç°ä»£æä½ç³»ç»çåºæ¬åè½ï¼å å
¶æ¯æ¬¡éè¦ä¿åä¿¡æ¯æ¢å¤ä¿¡æ¯ï¼è¿å°ä¼å ç¨ CPUï¼å
åçç³»ç»èµæºè¿è¡å¤çï¼ä¹å°±æå³çæç伿ä¸å®æèï¼å¦æé¢ç¹åæ¢å°±ä¼é ææ´ä½æçä½ä¸ã
### Thread#sleep() æ¹æ³å Object#wait() æ¹æ³å¯¹æ¯
**å
±åç¹**ï¼ä¸¤è
é½å¯ä»¥æå线ç¨çæ§è¡ã
**åºå«**ï¼
- **`sleep()` æ¹æ³æ²¡æéæ¾éï¼è `wait()` æ¹æ³éæ¾äºé** ã
- `wait()` é常被ç¨äºçº¿ç¨é´äº¤äº/éä¿¡ï¼`sleep()`é常被ç¨äºæåæ§è¡ã
- `wait()` æ¹æ³è¢«è°ç¨åï¼çº¿ç¨ä¸ä¼èªå¨èéï¼éè¦å«ç线ç¨è°ç¨åä¸ä¸ªå¯¹è±¡ä¸ç `notify()`æè
`notifyAll()` æ¹æ³ã`sleep()`æ¹æ³æ§è¡å®æåï¼çº¿ç¨ä¼èªå¨èéï¼æè
ä¹å¯ä»¥ä½¿ç¨ `wait(long timeout)` è¶
æ¶å线ç¨ä¼èªå¨èéã
- `sleep()` æ¯ `Thread` ç±»çéææ¬å°æ¹æ³ï¼`wait()` 忝 `Object` ç±»çæ¬å°æ¹æ³ã为ä»ä¹è¿æ ·è®¾è®¡å¢ï¼ä¸ä¸ä¸ªé®é¢å°±ä¼èå°ã
### 为ä»ä¹ wait() æ¹æ³ä¸å®ä¹å¨ Thread ä¸ï¼
`wait()` æ¯è®©è·å¾å¯¹è±¡éç线ç¨å®ç°çå¾
ï¼ä¼èªå¨éæ¾å½å线ç¨å æç对象éãæ¯ä¸ªå¯¹è±¡ï¼`Object`ï¼é½æ¥æå¯¹è±¡éï¼æ¢ç¶è¦éæ¾å½å线ç¨å æç对象é并让å
¶è¿å
¥ WAITING ç¶æï¼èªç¶æ¯è¦æä½å¯¹åºç对象ï¼`Object`ï¼èéå½åç线ç¨ï¼`Thread`ï¼ã
类似çé®é¢ï¼**为ä»ä¹ `sleep()` æ¹æ³å®ä¹å¨ `Thread` ä¸ï¼**
å 为 `sleep()` æ¯è®©å½åçº¿ç¨æåæ§è¡ï¼ä¸æ¶åå°å¯¹è±¡ç±»ï¼ä¹ä¸éè¦è·å¾å¯¹è±¡éã
### å¯ä»¥ç´æ¥è°ç¨ Thread ç±»ç run æ¹æ³åï¼
è¿æ¯å¦ä¸ä¸ªé常ç»å
¸ç Java å¤çº¿ç¨é¢è¯é®é¢ï¼èä¸å¨é¢è¯ä¸ä¼ç»å¸¸è¢«é®å°ãå¾ç®åï¼ä½æ¯å¾å¤äººé½ä¼çä¸ä¸æ¥ï¼
new ä¸ä¸ª `Thread`ï¼çº¿ç¨è¿å
¥äºæ°å»ºç¶æãè°ç¨ `start()`æ¹æ³ï¼ä¼å¯å¨ä¸ä¸ªçº¿ç¨å¹¶ä½¿çº¿ç¨è¿å
¥äºå°±ç»ªç¶æï¼å½åé
å°æ¶é´çåå°±å¯ä»¥å¼å§è¿è¡äºã `start()` 伿§è¡çº¿ç¨çç¸åºåå¤å·¥ä½ï¼ç¶åèªå¨æ§è¡ `run()` æ¹æ³çå
容ï¼è¿æ¯çæ£çå¤çº¿ç¨å·¥ä½ã 使¯ï¼ç´æ¥æ§è¡ `run()` æ¹æ³ï¼ä¼æ `run()` æ¹æ³å½æä¸ä¸ª main 线ç¨ä¸çæ®éæ¹æ³å»æ§è¡ï¼å¹¶ä¸ä¼å¨æä¸ªçº¿ç¨ä¸æ§è¡å®ï¼æä»¥è¿å¹¶ä¸æ¯å¤çº¿ç¨å·¥ä½ã
**æ»ç»ï¼è°ç¨ `start()` æ¹æ³æ¹å¯å¯å¨çº¿ç¨å¹¶ä½¿çº¿ç¨è¿å
¥å°±ç»ªç¶æï¼ç´æ¥æ§è¡ `run()` æ¹æ³çè¯ä¸ä¼ä»¥å¤çº¿ç¨çæ¹å¼æ§è¡ã**
## å¤çº¿ç¨
### å¹¶åä¸å¹¶è¡çåºå«
- **å¹¶å**ï¼ä¸¤ä¸ªå两个以ä¸çä½ä¸å¨åä¸ **æ¶é´æ®µ** å
æ§è¡ã
- **å¹¶è¡**ï¼ä¸¤ä¸ªå两个以ä¸çä½ä¸å¨åä¸ **æ¶å»** æ§è¡ã
æå
³é®çç¹æ¯ï¼æ¯å¦æ¯ **åæ¶** æ§è¡ã
### 忥å弿¥çåºå«
- **忥**ï¼ååºä¸ä¸ªè°ç¨ä¹åï¼å¨æ²¡æå¾å°ç»æä¹åï¼ è¯¥è°ç¨å°±ä¸å¯ä»¥è¿åï¼ä¸ç´çå¾
ã
- **弿¥**ï¼è°ç¨å¨ååºä¹åï¼ä¸ç¨çå¾
è¿åç»æï¼è¯¥è°ç¨ç´æ¥è¿åã
### âï¸ä¸ºä»ä¹è¦ä½¿ç¨å¤çº¿ç¨?
å
仿»ä½ä¸æ¥è¯´ï¼
- **ä»è®¡ç®æºåºå±æ¥è¯´ï¼** 线ç¨å¯ä»¥æ¯ä½æ¯è½»é级çè¿ç¨ï¼æ¯ç¨åºæ§è¡çæå°åä½ï¼çº¿ç¨é´ç忢åè°åº¦çææ¬è¿è¿å°äºè¿ç¨ãå¦å¤ï¼å¤æ ¸ CPU æ¶ä»£æå³çå¤ä¸ªçº¿ç¨å¯ä»¥åæ¶è¿è¡ï¼è¿åå°äºçº¿ç¨ä¸ä¸æåæ¢çå¼éã
- **ä»å½ä»£äºèç½åå±è¶å¿æ¥è¯´ï¼** ç°å¨çç³»ç»å¨ä¸å¨å°±è¦æ±ç¾ä¸çº§çè³åä¸çº§çå¹¶åéï¼èå¤çº¿ç¨å¹¶åç¼ç¨æ£æ¯å¼åé«å¹¶åç³»ç»çåºç¡ï¼å©ç¨å¥½å¤çº¿ç¨æºå¶å¯ä»¥å¤§å¤§æé«ç³»ç»æ´ä½çå¹¶åè½å以忧è½ã
åæ·±å
¥å°è®¡ç®æºåºå±æ¥æ¢è®¨ï¼
- **åæ ¸æ¶ä»£**ï¼å¨åæ ¸æ¶ä»£å¤çº¿ç¨ä¸»è¦æ¯ä¸ºäºæé«åè¿ç¨å©ç¨ CPU å IO ç³»ç»çæçã å设åªè¿è¡äºä¸ä¸ª Java è¿ç¨çæ
åµï¼å½æä»¬è¯·æ± IO çæ¶åï¼å¦æ Java è¿ç¨ä¸åªæä¸ä¸ªçº¿ç¨ï¼æ¤çº¿ç¨è¢« IO é»å¡åæ´ä¸ªè¿ç¨è¢«é»å¡ãCPU å IO 设å¤åªæä¸ä¸ªå¨è¿è¡ï¼é£ä¹å¯ä»¥ç®åå°è¯´ç³»ç»æ´ä½æçåªæ 50%ãå½ä½¿ç¨å¤çº¿ç¨çæ¶åï¼ä¸ä¸ªçº¿ç¨è¢« IO é»å¡ï¼å
¶ä»çº¿ç¨è¿å¯ä»¥ç»§ç»ä½¿ç¨ CPUãä»èæé«äº Java è¿ç¨å©ç¨ç³»ç»èµæºçæ´ä½æçã
- **夿 ¸æ¶ä»£**: 夿 ¸æ¶ä»£å¤çº¿ç¨ä¸»è¦æ¯ä¸ºäºæé«è¿ç¨å©ç¨å¤æ ¸ CPU çè½åã举个ä¾åï¼å妿们è¦è®¡ç®ä¸ä¸ªå¤æçä»»å¡ï¼æä»¬åªç¨ä¸ä¸ªçº¿ç¨çè¯ï¼ä¸è®ºç³»ç»æå 个 CPU æ ¸å¿ï¼é½åªä¼æä¸ä¸ª CPU æ ¸å¿è¢«å©ç¨å°ãèå建å¤ä¸ªçº¿ç¨ï¼è¿äºçº¿ç¨å¯ä»¥è¢«æ å°å°åºå±å¤ä¸ª CPU æ ¸å¿ä¸æ§è¡ï¼å¨ä»»å¡ä¸çå¤ä¸ªçº¿ç¨æ²¡æèµæºç«äºçæ
åµä¸ï¼ä»»å¡æ§è¡çæç伿æ¾èæ§çæé«ï¼çº¦çäºï¼åæ ¸æ¶æ§è¡æ¶é´/CPU æ ¸å¿æ°ï¼ã
### âï¸åæ ¸ CPU æ¯æ Java å¤çº¿ç¨åï¼
åæ ¸ CPU æ¯æ¯æ Java å¤çº¿ç¨çãæä½ç³»ç»éè¿æ¶é´çè½®è½¬çæ¹å¼ï¼å° CPU çæ¶é´åé
ç»ä¸åç线ç¨ãå°½ç®¡åæ ¸ CPU 䏿¬¡åªè½æ§è¡ä¸ä¸ªä»»å¡ï¼ä½éè¿å¿«éå¨å¤ä¸ªçº¿ç¨ä¹é´åæ¢ï¼å¯ä»¥è®©ç¨æ·æè§å¤ä¸ªä»»å¡æ¯åæ¶è¿è¡çã
è¿é顺带æä¸ä¸ Java 使ç¨ç线ç¨è°åº¦æ¹å¼ã
æä½ç³»ç»ä¸»è¦éè¿ä¸¤ç§çº¿ç¨è°åº¦æ¹å¼æ¥ç®¡çå¤çº¿ç¨çæ§è¡ï¼
- **æ¢å å¼è°åº¦ï¼Preemptive Schedulingï¼**ï¼æä½ç³»ç»å³å®ä½æ¶æåå½åæ£å¨è¿è¡ç线ç¨ï¼å¹¶åæ¢å°å¦ä¸ä¸ªçº¿ç¨æ§è¡ãè¿ç§åæ¢é常æ¯ç±ç³»ç»æ¶éä¸æï¼æ¶é´çè½®è½¬ï¼æå
¶ä»é«ä¼å
级äºä»¶ï¼å¦ I/O æä½å®æï¼è§¦åçãè¿ç§æ¹å¼åå¨ä¸ä¸æåæ¢å¼éï¼ä½å
¬å¹³æ§å CPU èµæºå©ç¨çè¾å¥½ï¼ä¸æé»å¡ã
- **ååå¼è°åº¦ï¼Cooperative Schedulingï¼**ï¼çº¿ç¨æ§è¡å®æ¯åï¼ä¸»å¨éç¥ç³»ç»åæ¢å°å¦ä¸ä¸ªçº¿ç¨ãè¿ç§æ¹å¼å¯ä»¥åå°ä¸ä¸æåæ¢å¸¦æ¥çæ§è½å¼éï¼ä½å
¬å¹³æ§è¾å·®ï¼å®¹æé»å¡ã
Java 使ç¨ç线ç¨è°åº¦æ¯æ¢å å¼çãä¹å°±æ¯è¯´ï¼JVM æ¬èº«ä¸è´è´£çº¿ç¨çè°åº¦ï¼èæ¯å°çº¿ç¨çè°åº¦å§æç»æä½ç³»ç»ãæä½ç³»ç»é常ä¼åºäºçº¿ç¨ä¼å
çº§åæ¶é´çæ¥è°åº¦çº¿ç¨çæ§è¡ï¼é«ä¼å
级ç线ç¨é常è·å¾ CPU æ¶é´ççæºä¼æ´å¤ã
### âï¸åæ ¸ CPU ä¸è¿è¡å¤ä¸ªçº¿ç¨æçä¸å®ä¼é«åï¼
åæ ¸ CPU åæ¶è¿è¡å¤ä¸ªçº¿ç¨çæçæ¯å¦ä¼é«ï¼åå³äºçº¿ç¨çç±»ååä»»å¡çæ§è´¨ãä¸è¬æ¥è¯´ï¼æä¸¤ç§ç±»åç线ç¨ï¼
1. **CPU å¯éå**ï¼CPU å¯éåç线ç¨ä¸»è¦è¿è¡è®¡ç®åé»è¾å¤çï¼éè¦å ç¨å¤§éç CPU èµæºã
2. **IO å¯éå**ï¼IO å¯éåç线ç¨ä¸»è¦è¿è¡è¾å
¥è¾åºæä½ï¼å¦è¯»åæä»¶ãç½ç»éä¿¡çï¼éè¦çå¾
IO 设å¤çååºï¼èä¸å ç¨å¤ªå¤ç CPU èµæºã
å¨åæ ¸ CPU ä¸ï¼å䏿¶å»åªè½æä¸ä¸ªçº¿ç¨å¨è¿è¡ï¼å
¶ä»çº¿ç¨éè¦çå¾
CPU çæ¶é´çåé
ãå¦æçº¿ç¨æ¯ CPU å¯éåçï¼é£ä¹å¤ä¸ªçº¿ç¨åæ¶è¿è¡ä¼å¯¼è´é¢ç¹ç线ç¨åæ¢ï¼å¢å äºç³»ç»çå¼éï¼éä½äºæçãå¦æçº¿ç¨æ¯ IO å¯éåçï¼é£ä¹å¤ä¸ªçº¿ç¨åæ¶è¿è¡å¯ä»¥å©ç¨ CPU å¨çå¾
IO æ¶çç©ºé²æ¶é´ï¼æé«äºæçã
å æ¤ï¼å¯¹äºåæ ¸ CPU æ¥è¯´ï¼å¦æä»»å¡æ¯ CPU å¯éåçï¼é£ä¹å¼å¾å¤çº¿ç¨ä¼å½±åæçï¼å¦æä»»å¡æ¯ IO å¯éåçï¼é£ä¹å¼å¾å¤çº¿ç¨ä¼æé«æçãå½ç¶ï¼è¿éçâå¾å¤âä¹è¦é度ï¼ä¸è½è¶
è¿ç³»ç»è½å¤æ¿åçä¸éã
### 使ç¨å¤çº¿ç¨å¯è½å¸¦æ¥ä»ä¹é®é¢?
å¹¶åç¼ç¨çç®çå°±æ¯ä¸ºäºè½æé«ç¨åºçæ§è¡æçè¿èæé«ç¨åºçè¿è¡é度ï¼ä½æ¯å¹¶åç¼ç¨å¹¶ä¸æ»æ¯è½æé«ç¨åºè¿è¡é度çï¼èä¸å¹¶åç¼ç¨å¯è½ä¼éå°å¾å¤é®é¢ï¼æ¯å¦ï¼å
åæ³æ¼ãæ»éã线ç¨ä¸å®å
¨ççã
### å¦ä½ç解线ç¨å®å
¨åä¸å®å
¨ï¼
线ç¨å®å
¨åä¸å®å
¨æ¯å¨å¤çº¿ç¨ç¯å¢ä¸å¯¹äºåä¸ä»½æ°æ®çè®¿é®æ¯å¦è½å¤ä¿è¯å
¶æ£ç¡®æ§åä¸è´æ§çæè¿°ã
- 线ç¨å®å
¨æçæ¯å¨å¤çº¿ç¨ç¯å¢ä¸ï¼å¯¹äºåä¸ä»½æ°æ®ï¼ä¸ç®¡æå¤å°ä¸ªçº¿ç¨åæ¶è®¿é®ï¼é½è½ä¿è¯è¿ä»½æ°æ®çæ£ç¡®æ§åä¸è´æ§ã
- 线ç¨ä¸å®å
¨å表示å¨å¤çº¿ç¨ç¯å¢ä¸ï¼å¯¹äºåä¸ä»½æ°æ®ï¼å¤ä¸ªçº¿ç¨åæ¶è®¿é®æ¶å¯è½ä¼å¯¼è´æ°æ®æ··ä¹±ãé误æè
丢失ã
## âï¸æ»é
### ä»ä¹æ¯çº¿ç¨æ»éï¼
çº¿ç¨æ»éæè¿°çæ¯è¿æ ·ä¸ç§æ
åµï¼å¤ä¸ªçº¿ç¨åæ¶è¢«é»å¡ï¼å®ä»¬ä¸çä¸ä¸ªæè
å
¨é¨é½å¨çå¾
æä¸ªèµæºè¢«éæ¾ãç±äºçº¿ç¨è¢«æ éæå°é»å¡ï¼å æ¤ç¨åºä¸å¯è½æ£å¸¸ç»æ¢ã
å¦ä¸å¾æç¤ºï¼çº¿ç¨ A ææèµæº 2ï¼çº¿ç¨ B ææèµæº 1ï¼ä»ä»¬åæ¶é½æ³ç³è¯·å¯¹æ¹çèµæºï¼æä»¥è¿ä¸¤ä¸ªçº¿ç¨å°±ä¼äºç¸çå¾
èè¿å
¥æ»éç¶æã

ä¸é¢éè¿ä¸ä¸ªä¾åæ¥è¯´æçº¿ç¨æ»é,ä»£ç æ¨¡æäºä¸å¾çæ»éçæ
åµ (ä»£ç æ¥æºäºãå¹¶åç¼ç¨ä¹ç¾ã)ï¼
```java
public class DeadLockDemo {
private static Object resource1 = new Object();//èµæº 1
private static Object resource2 = new Object();//èµæº 2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "çº¿ç¨ 1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "çº¿ç¨ 2").start();
}
}
```
Output
```plain
Thread[çº¿ç¨ 1,5,main]get resource1
Thread[çº¿ç¨ 2,5,main]get resource2
Thread[çº¿ç¨ 1,5,main]waiting get resource2
Thread[çº¿ç¨ 2,5,main]waiting get resource1
```
çº¿ç¨ A éè¿ `synchronized (resource1)` è·å¾ `resource1` ççè§å¨éï¼ç¶åéè¿ `Thread.sleep(1000);` è®©çº¿ç¨ A ä¼ç 1sï¼ä¸ºçæ¯è®©çº¿ç¨ B å¾å°æ§è¡ç¶åè·åå° resource2 ççè§å¨éãçº¿ç¨ A åçº¿ç¨ B ä¼ç ç»æäºé½å¼å§ä¼å¾è¯·æ±è·å对æ¹çèµæºï¼ç¶åè¿ä¸¤ä¸ªçº¿ç¨å°±ä¼é·å
¥äºç¸çå¾
çç¶æï¼è¿ä¹å°±äº§çäºæ»éã
ä¸é¢çä¾å符åäº§çæ»éçå个å¿
è¦æ¡ä»¶ï¼
1. **äºæ¥æ¡ä»¶**ï¼è¯¥èµæºä»»æä¸ä¸ªæ¶å»åªç±ä¸ä¸ªçº¿ç¨å ç¨ã
2. **请æ±ä¸ä¿ææ¡ä»¶**ï¼ä¸ä¸ªçº¿ç¨å 请æ±èµæºèé»å¡æ¶ï¼å¯¹å·²è·å¾çèµæºä¿æä¸æ¾ã
3. **ä¸å¥å¤ºæ¡ä»¶**ï¼çº¿ç¨å·²è·å¾çèµæºå¨æªä½¿ç¨å®ä¹åä¸è½è¢«å
¶ä»çº¿ç¨å¼ºè¡å¥å¤ºï¼åªæèªå·±ä½¿ç¨å®æ¯åæéæ¾èµæºã
4. **循ç¯çå¾
æ¡ä»¶**ï¼è¥å¹²çº¿ç¨ä¹é´å½¢æä¸ç§å¤´å°¾ç¸æ¥ç循ç¯çå¾
èµæºå
³ç³»ã
### å¦ä½æ£æµæ»éï¼
- 使ç¨`jmap`ã`jstack`çå½ä»¤æ¥ç JVM çº¿ç¨æ åå å
åçæ
åµãå¦æææ»éï¼`jstack` çè¾åºä¸é叏伿 `Found one Java-level deadlock:`çåæ ·ï¼åé¢ä¼è·çæ»éç¸å
³ç线ç¨ä¿¡æ¯ãå¦å¤ï¼å®é
项ç®ä¸è¿å¯ä»¥æé
使ç¨`top`ã`df`ã`free`çå½ä»¤æ¥çæä½ç³»ç»çåºæ¬æ
åµï¼åºç°æ»éå¯è½ä¼å¯¼è´ CPUãå
åçèµæºæ¶èè¿é«ã
- éç¨ VisualVMãJConsole çå·¥å
·è¿è¡ææ¥ã
è¿é以 JConsole å·¥å
·ä¸ºä¾è¿è¡æ¼ç¤ºã
é¦å
ï¼æä»¬è¦æ¾å° JDK ç bin ç®å½ï¼æ¾å° jconsole å¹¶å廿å¼ã

å¯¹äº MAC ç¨æ·æ¥è¯´ï¼å¯ä»¥éè¿ `/usr/libexec/java_home -V`æ¥ç JDK å®è£
ç®å½ï¼æ¾å°åéè¿ `open . + æä»¶å¤¹å°å`æå¼å³å¯ãä¾å¦ï¼ææ¬å°çæä¸ª JDK çè·¯å¾æ¯ï¼
```bash
open . /Users/guide/Library/Java/JavaVirtualMachines/corretto-1.8.0_252/Contents/Home
```
æå¼ jconsole åï¼è¿æ¥å¯¹åºçç¨åºï¼ç¶åè¿å
¥çº¿ç¨çé¢éæ©æ£æµæ»éå³å¯ï¼


### å¦ä½é¢é²åé¿å
çº¿ç¨æ»é?
**å¦ä½é¢é²æ»éï¼** ç ´åæ»éç产ççå¿
è¦æ¡ä»¶å³å¯ï¼
1. **ç ´å请æ±ä¸ä¿ææ¡ä»¶**ï¼ä¸æ¬¡æ§ç³è¯·ææçèµæºã
2. **ç ´åä¸å¥å¤ºæ¡ä»¶**ï¼å ç¨é¨åèµæºç线ç¨è¿ä¸æ¥ç³è¯·å
¶ä»èµæºæ¶ï¼å¦æç³è¯·ä¸å°ï¼å¯ä»¥ä¸»å¨éæ¾å®å æçèµæºã
3. **ç ´å循ç¯çå¾
æ¡ä»¶**ï¼é æåºç³è¯·èµæºæ¥é¢é²ãææä¸é¡ºåºç³è¯·èµæºï¼éæ¾èµæºåååºéæ¾ãç ´å循ç¯çå¾
æ¡ä»¶ã
**å¦ä½é¿å
æ»éï¼**
é¿å
æ»éå°±æ¯å¨èµæºåé
æ¶ï¼åå©äºç®æ³ï¼æ¯å¦é¶è¡å®¶ç®æ³ï¼å¯¹èµæºåé
è¿è¡è®¡ç®è¯ä¼°ï¼ä½¿å
¶è¿å
¥å®å
¨ç¶æã
> **å®å
¨ç¶æ** æçæ¯ç³»ç»è½å¤æç
§æç§çº¿ç¨æ¨è¿é¡ºåºï¼P1ãP2ãP3â¦â¦Pnï¼æ¥ä¸ºæ¯ä¸ªçº¿ç¨åé
æéèµæºï¼ç´å°æ»¡è¶³æ¯ä¸ªçº¿ç¨å¯¹èµæºçæå¤§éæ±ï¼ä½¿æ¯ä¸ªçº¿ç¨é½å¯é¡ºå©å®æãç§° `` åºå为å®å
¨åºåã
æä»¬å¯¹çº¿ç¨ 2 ç代ç ä¿®æ¹æä¸é¢è¿æ ·å°±ä¸ä¼äº§çæ»éäºã
```java
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "çº¿ç¨ 2").start();
```
è¾åºï¼
```plain
Thread[çº¿ç¨ 1,5,main]get resource1
Thread[çº¿ç¨ 1,5,main]waiting get resource2
Thread[çº¿ç¨ 1,5,main]get resource2
Thread[çº¿ç¨ 2,5,main]get resource1
Thread[çº¿ç¨ 2,5,main]waiting get resource2
Thread[çº¿ç¨ 2,5,main]get resource2
Process finished with exit code 0
```
æä»¬åæä¸ä¸ä¸é¢ç代ç 为ä»ä¹é¿å
äºæ»éçåç?
çº¿ç¨ 1 é¦å
è·å¾å° resource1 ççè§å¨é,è¿æ¶åçº¿ç¨ 2 å°±è·åä¸å°äºãç¶åçº¿ç¨ 1 åå»è·å resource2 ççè§å¨éï¼å¯ä»¥è·åå°ãç¶åçº¿ç¨ 1 éæ¾äºå¯¹ resource1ãresource2 ççè§å¨éçå ç¨ï¼çº¿ç¨ 2 è·åå°å°±å¯ä»¥æ§è¡äºãè¿æ ·å°±ç ´åäºå¾ªç¯çå¾
æ¡ä»¶ï¼å æ¤é¿å
äºæ»éã
## âï¸JMM(Java å
忍¡å)
JMMï¼Java å
忍¡åï¼ç¸å
³çé®é¢æ¯è¾å¤ï¼ä¹æ¯è¾éè¦ï¼äºæ¯æåç¬æ½äºä¸ç¯æç« æ¥æ»ç» JMM ç¸å
³çç¥è¯ç¹åé®é¢ï¼[JMMï¼Java å
忍¡åï¼è¯¦è§£](https://javaguide.cn/java/concurrent/jmm.html) ã
## âï¸volatile å
³é®å
### å¦ä½ä¿è¯åéçå¯è§æ§ï¼
å¨ Java ä¸ï¼`volatile` å
³é®åå¯ä»¥ä¿è¯åéçå¯è§æ§ï¼å¦ææä»¬å°åé声æä¸º **`volatile`** ï¼è¿å°±æç¤º JVMï¼è¿ä¸ªå鿝å
±äº«ä¸ä¸ç¨³å®çï¼æ¯æ¬¡ä½¿ç¨å®é½å°ä¸»åä¸è¿è¡è¯»åã


`volatile` å
³é®åå
¶å®å¹¶éæ¯ Java è¯è¨ç¹æçï¼å¨ C è¯è¨é乿ï¼å®æåå§çæä¹å°±æ¯ç¦ç¨ CPU ç¼åã妿æä»¬å°ä¸ä¸ªåéä½¿ç¨ `volatile` 修饰ï¼è¿å°±æç¤º ç¼è¯å¨ï¼è¿ä¸ªå鿝å
±äº«ä¸ä¸ç¨³å®çï¼æ¯æ¬¡ä½¿ç¨å®é½å°ä¸»åä¸è¿è¡è¯»åã
`volatile` å
³é®åè½ä¿è¯æ°æ®çå¯è§æ§ï¼ä½ä¸è½ä¿è¯æ°æ®çååæ§ã`synchronized` å
³é®å两è
é½è½ä¿è¯ã
### å¦ä½ç¦æ¢æä»¤éæåºï¼
**å¨ Java ä¸ï¼`volatile` å
³é®åé¤äºå¯ä»¥ä¿è¯åéçå¯è§æ§ï¼è¿æä¸ä¸ªéè¦çä½ç¨å°±æ¯é²æ¢ JVM çæä»¤éæåºã** 妿æä»¬å°åé声æä¸º **`volatile`** ï¼å¨å¯¹è¿ä¸ªåéè¿è¡è¯»åæä½çæ¶åï¼ä¼éè¿æå
¥ç¹å®ç **å
åå±é** çæ¹å¼æ¥ç¦æ¢æä»¤éæåºã
å¨ Java ä¸ï¼`Unsafe` ç±»æä¾äºä¸ä¸ªå¼ç®±å³ç¨çå
åå±éç¸å
³çæ¹æ³ï¼å±è½äºæä½ç³»ç»åºå±çå·®å¼ï¼
```java
public native void loadFence();
public native void storeFence();
public native void fullFence();
```
çè®ºä¸æ¥è¯´ï¼ä½ éè¿è¿ä¸ªä¸ä¸ªæ¹æ³ä¹å¯ä»¥å®ç°å`volatile`ç¦æ¢éæåºä¸æ ·çææï¼åªæ¯ä¼éº»ç¦ä¸äºã
ä¸é¢æä»¥ä¸ä¸ªå¸¸è§çé¢è¯é¢ä¸ºä¾è®²è§£ä¸ä¸ `volatile` å
³é®åç¦æ¢æä»¤éæåºçææã
é¢è¯ä¸é¢è¯å®ç»å¸¸ä¼è¯´ï¼âå便¨¡å¼äºè§£åï¼æ¥ç»ææåä¸ä¸ï¼ç»æè§£éä¸ä¸å鿣éªéæ¹å¼å®ç°å便¨¡å¼çåçåï¼â
**åéæ ¡éªéå®ç°å¯¹è±¡åä¾ï¼çº¿ç¨å®å
¨ï¼**ï¼
```java
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
//å
å¤æå¯¹è±¡æ¯å¦å·²ç»å®ä¾è¿ï¼æ²¡æå®ä¾åè¿æè¿å
¥å é代ç
if (uniqueInstance == null) {
//类对象å é
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
```
`uniqueInstance` éç¨ `volatile` å
³é®åä¿®é¥°ä¹æ¯å¾æå¿
è¦çï¼ `uniqueInstance = new Singleton();` è¿æ®µä»£ç å
¶å®æ¯åä¸ºä¸æ¥æ§è¡ï¼
1. 为 `uniqueInstance` åé
å
å空é´
2. åå§å `uniqueInstance`
3. å° `uniqueInstance` æååé
çå
åå°å
使¯ç±äº JVM å
·ææä»¤éæçç¹æ§ï¼æ§è¡é¡ºåºæå¯è½åæ 1->3->2ãæä»¤éæå¨å线ç¨ç¯å¢ä¸ä¸ä¼åºç°é®é¢ï¼ä½æ¯å¨å¤çº¿ç¨ç¯å¢ä¸ä¼å¯¼è´ä¸ä¸ªçº¿ç¨è·å¾è¿æ²¡æåå§åçå®ä¾ãä¾å¦ï¼çº¿ç¨ T1 æ§è¡äº 1 å 3ï¼æ¤æ¶ T2 è°ç¨ `getUniqueInstance`() ååç° `uniqueInstance` ä¸ä¸ºç©ºï¼å æ¤è¿å `uniqueInstance`ï¼ä½æ¤æ¶ `uniqueInstance` è¿æªè¢«åå§åã
### volatile å¯ä»¥ä¿è¯ååæ§ä¹ï¼
**`volatile` å
³é®åè½ä¿è¯åéçå¯è§æ§ï¼ä½ä¸è½ä¿è¯å¯¹åéçæä½æ¯ååæ§çã**
æä»¬éè¿ä¸é¢ç代ç å³å¯è¯æï¼
```java
/**
* 微信æ JavaGuide åå¤"é¢è¯çªå»"å³å¯å
è´¹é¢å个人ååç Java é¢è¯æå
*
* @author Guideå¥
* @date 2022/08/03 13:40
**/
public class VolatileAtomicityDemo {
public volatile static int inc = 0;
public void increase() {
inc++;
}
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
VolatileAtomicityDemo volatileAtomicityDemo = new VolatileAtomicityDemo();
for (int i = 0; i < 5; i++) {
threadPool.execute(() -> {
for (int j = 0; j < 500; j++) {
volatileAtomicityDemo.increase();
}
});
}
// çå¾
1.5ç§ï¼ä¿è¯ä¸é¢ç¨åºæ§è¡å®æ
Thread.sleep(1500);
System.out.println(inc);
threadPool.shutdown();
}
}
```
æ£å¸¸æ
åµä¸ï¼è¿è¡ä¸é¢ç代ç çåºè¾åº `2500`ãä½ä½ çæ£è¿è¡äºä¸é¢ç代ç ä¹åï¼ä½ ä¼åç°æ¯æ¬¡è¾åºç»æé½å°äº `2500`ã
为ä»ä¹ä¼åºç°è¿ç§æ
åµå¢ï¼ä¸æ¯è¯´å¥½äºï¼`volatile` å¯ä»¥ä¿è¯åéçå¯è§æ§åï¼
ä¹å°±æ¯è¯´ï¼å¦æ `volatile` è½ä¿è¯ `inc++` æä½çååæ§çè¯ãæ¯ä¸ªçº¿ç¨ä¸å¯¹ `inc` åéèªå¢å®ä¹åï¼å
¶ä»çº¿ç¨å¯ä»¥ç«å³çå°ä¿®æ¹åçå¼ã5 个线ç¨åå«è¿è¡äº 500 次æä½ï¼é£ä¹æç» inc çå¼åºè¯¥æ¯ 5\*500=2500ã
å¾å¤äººä¼è¯¯è®¤ä¸ºèªå¢æä½ `inc++` æ¯ååæ§çï¼å®é
ä¸ï¼`inc++` å
¶å®æ¯ä¸ä¸ªå¤åæä½ï¼å
æ¬ä¸æ¥ï¼
1. 读å inc çå¼ã
2. 对 inc å 1ã
3. å° inc çå¼ååå
åã
`volatile` æ¯æ æ³ä¿è¯è¿ä¸ä¸ªæä½æ¯å
·æååæ§çï¼æå¯è½å¯¼è´ä¸é¢è¿ç§æ
åµåºç°ï¼
1. çº¿ç¨ 1 对 `inc` è¿è¡è¯»åæä½ä¹åï¼è¿æªå¯¹å
¶è¿è¡ä¿®æ¹ãçº¿ç¨ 2 å读åäº `inc`çå¼å¹¶å¯¹å
¶è¿è¡ä¿®æ¹ï¼+1ï¼ï¼åå°`inc` çå¼ååå
åã
2. çº¿ç¨ 2 æä½å®æ¯åï¼çº¿ç¨ 1 对 `inc`çå¼è¿è¡ä¿®æ¹ï¼+1ï¼ï¼åå°`inc` çå¼ååå
åã
è¿ä¹å°±å¯¼è´ä¸¤ä¸ªçº¿ç¨åå«å¯¹ `inc` è¿è¡äºä¸æ¬¡èªå¢æä½åï¼`inc` å®é
ä¸åªå¢å äº 1ã
å
¶å®ï¼å¦ææ³è¦ä¿è¯ä¸é¢ç代ç è¿è¡æ£ç¡®ä¹é常ç®åï¼å©ç¨ `synchronized`ã`Lock`æè
`AtomicInteger`é½å¯ä»¥ã
ä½¿ç¨ `synchronized` æ¹è¿ï¼
```java
public synchronized void increase() {
inc++;
}
```
ä½¿ç¨ `AtomicInteger` æ¹è¿ï¼
```java
public AtomicInteger inc = new AtomicInteger();
public void increase() {
inc.getAndIncrement();
}
```
ä½¿ç¨ `ReentrantLock` æ¹è¿ï¼
```java
Lock lock = new ReentrantLock();
public void increase() {
lock.lock();
try {
inc++;
} finally {
lock.unlock();
}
}
```
## âï¸ä¹è§éåæ²è§é
### ä»ä¹æ¯æ²è§éï¼
æ²è§éæ»æ¯å设æåçæ
åµï¼è®¤ä¸ºå
±äº«èµæºæ¯æ¬¡è¢«è®¿é®çæ¶åå°±ä¼åºç°é®é¢(æ¯å¦å
±äº«æ°æ®è¢«ä¿®æ¹)ï¼æä»¥æ¯æ¬¡å¨è·åèµæºæä½çæ¶åé½ä¼ä¸éï¼è¿æ ·å
¶ä»çº¿ç¨æ³æ¿å°è¿ä¸ªèµæºå°±ä¼é»å¡ç´å°é被ä¸ä¸ä¸ªææè
éæ¾ãä¹å°±æ¯è¯´ï¼**å
±äº«èµæºæ¯æ¬¡åªç»ä¸ä¸ªçº¿ç¨ä½¿ç¨ï¼å
¶å®çº¿ç¨é»å¡ï¼ç¨å®ååæèµæºè½¬è®©ç»å
¶å®çº¿ç¨**ã
å Java ä¸`synchronized`å`ReentrantLock`çç¬å éå°±æ¯æ²è§éææ³çå®ç°ã
```java
public void performSynchronisedTask() {
synchronized (this) {
// éè¦åæ¥çæä½
}
}
private Lock lock = new ReentrantLock();
lock.lock();
try {
// éè¦åæ¥çæä½
} finally {
lock.unlock();
}
```
é«å¹¶åçåºæ¯ä¸ï¼æ¿ççéç«äºä¼é æçº¿ç¨é»å¡ï¼å¤§éé»å¡çº¿ç¨ä¼å¯¼è´ç³»ç»çä¸ä¸æåæ¢ï¼å¢å ç³»ç»çæ§è½å¼éãå¹¶ä¸ï¼æ²è§éè¿å¯è½ä¼å卿»éé®é¢ï¼å½±å代ç çæ£å¸¸è¿è¡ã
### ä»ä¹æ¯ä¹è§éï¼
ä¹è§éæ»æ¯å设æå¥½çæ
åµï¼è®¤ä¸ºå
±äº«èµæºæ¯æ¬¡è¢«è®¿é®çæ¶åä¸ä¼åºç°é®é¢ï¼çº¿ç¨å¯ä»¥ä¸åå°æ§è¡ï¼æ éå é乿 éçå¾
ï¼åªæ¯å¨æäº¤ä¿®æ¹çæ¶åå»éªè¯å¯¹åºçèµæºï¼ä¹å°±æ¯æ°æ®ï¼æ¯å¦è¢«å
¶å®çº¿ç¨ä¿®æ¹äºï¼å
·ä½æ¹æ³å¯ä»¥ä½¿ç¨çæ¬å·æºå¶æ CAS ç®æ³ï¼ã
å¨ Java ä¸`java.util.concurrent.atomic`å
ä¸é¢çåååéç±»ï¼æ¯å¦`AtomicInteger`ã`LongAdder`ï¼å°±æ¯ä½¿ç¨äºä¹è§éçä¸ç§å®ç°æ¹å¼ **CAS** å®ç°çã

```java
// LongAdder å¨é«å¹¶ååºæ¯ä¸ä¼æ¯ AtomicInteger å AtomicLong çæ§è½æ´å¥½
// 代价就æ¯ä¼æ¶èæ´å¤çå
å空é´ï¼ç©ºé´æ¢æ¶é´ï¼
LongAdder sum = new LongAdder();
sum.increment();
```
é«å¹¶åçåºæ¯ä¸ï¼ä¹è§éç¸æ¯æ²è§éæ¥è¯´ï¼ä¸åå¨éç«äºé æçº¿ç¨é»å¡ï¼ä¹ä¸ä¼ææ»éçé®é¢ï¼å¨æ§è½ä¸å¾å¾ä¼æ´èä¸ç¹ã使¯ï¼å¦æå²çªé¢ç¹åçï¼åå æ¯é常å¤çæ
åµï¼ï¼ä¼é¢ç¹å¤±è´¥åéè¯ï¼è¿æ ·åæ ·ä¼é叏影忧è½ï¼å¯¼è´ CPU é£åã
ä¸è¿ï¼å¤§é失败éè¯çé®é¢ä¹æ¯å¯ä»¥è§£å³çï¼åæä»¬å颿å°ç `LongAdder`ä»¥ç©ºé´æ¢æ¶é´çæ¹å¼å°±è§£å³äºè¿ä¸ªé®é¢ã
çè®ºä¸æ¥è¯´ï¼
- æ²è§éé常å¤ç¨äºåæ¯è¾å¤çæ
åµï¼å¤ååºæ¯ï¼ç«äºæ¿çï¼ï¼è¿æ ·å¯ä»¥é¿å
é¢ç¹å¤±è´¥åéè¯å½±åæ§è½ï¼æ²è§éçå¼éæ¯åºå®çãä¸è¿ï¼å¦æä¹è§éè§£å³äºé¢ç¹å¤±è´¥åéè¯è¿ä¸ªé®é¢çè¯ï¼æ¯å¦`LongAdder`ï¼ï¼ä¹æ¯å¯ä»¥èè使ç¨ä¹è§éçï¼è¦è§å®é
æ
åµèå®ã
- ä¹è§éé常å¤ç¨äºåæ¯è¾å°çæ
åµï¼å¤è¯»åºæ¯ï¼ç«äºè¾å°ï¼ï¼è¿æ ·å¯ä»¥é¿å
é¢ç¹å é影忧è½ãä¸è¿ï¼ä¹è§é主è¦é对ç对象æ¯å个å
±äº«åéï¼åè`java.util.concurrent.atomic`å
ä¸é¢çåååéç±»ï¼ã
### å¦ä½å®ç°ä¹è§éï¼
ä¹è§éä¸è¬ä¼ä½¿ç¨çæ¬å·æºå¶æ CAS ç®æ³å®ç°ï¼CAS ç®æ³ç¸å¯¹æ¥è¯´æ´å¤ä¸äºï¼è¿ééè¦æ ¼å¤æ³¨æã
#### çæ¬å·æºå¶
ä¸è¬æ¯å¨æ°æ®è¡¨ä¸å ä¸ä¸ä¸ªæ°æ®çæ¬å· `version` åæ®µï¼è¡¨ç¤ºæ°æ®è¢«ä¿®æ¹ç次æ°ã彿°æ®è¢«ä¿®æ¹æ¶ï¼`version` å¼ä¼å ä¸ãå½çº¿ç¨ A è¦æ´æ°æ°æ®å¼æ¶ï¼å¨è¯»åæ°æ®çåæ¶ä¹ä¼è¯»å `version` å¼ï¼å¨æäº¤æ´æ°æ¶ï¼è¥åæè¯»åå°ç version å¼ä¸ºå½åæ°æ®åºä¸ç `version` å¼ç¸çæ¶ææ´æ°ï¼å¦åéè¯æ´æ°æä½ï¼ç´å°æ´æ°æåã
**举ä¸ä¸ªç®åçä¾å**ï¼åè®¾æ°æ®åºä¸å¸æ·ä¿¡æ¯è¡¨ä¸æä¸ä¸ª version åæ®µï¼å½åå¼ä¸º 1 ï¼èå½å叿·ä½é¢åæ®µï¼ `balance` ï¼ä¸º \$100 ã
1. æä½å A æ¤æ¶å°å
¶è¯»åºï¼ `version`=1 ï¼ï¼å¹¶ä»å
¶å¸æ·ä½é¢ä¸æ£é¤ $50ï¼ $100-\$50 ï¼ã
2. 卿ä½å A æä½çè¿ç¨ä¸ï¼æä½å B ä¹è¯»å
¥æ¤ç¨æ·ä¿¡æ¯ï¼ `version`=1 ï¼ï¼å¹¶ä»å
¶å¸æ·ä½é¢ä¸æ£é¤ $20 ï¼ $100-\$20 ï¼ã
3. æä½å A 宿äºä¿®æ¹å·¥ä½ï¼å°æ°æ®çæ¬å·ï¼ `version`=1 ï¼ï¼è¿å叿·æ£é¤åä½é¢ï¼ `balance`=\$50 ï¼ï¼æäº¤è³æ°æ®åºæ´æ°ï¼æ¤æ¶ç±äºæäº¤æ°æ®çæ¬çäºæ°æ®åºè®°å½å½åçæ¬ï¼æ°æ®è¢«æ´æ°ï¼æ°æ®åºè®°å½ `version` æ´æ°ä¸º 2 ã
4. æä½å B å®æäºæä½ï¼ä¹å°çæ¬å·ï¼ `version`=1 ï¼è¯å¾åæ°æ®åºæäº¤æ°æ®ï¼ `balance`=\$80 ï¼ï¼ä½æ¤æ¶æ¯å¯¹æ°æ®åºè®°å½çæ¬æ¶åç°ï¼æä½å B æäº¤çæ°æ®çæ¬å·ä¸º 1 ï¼æ°æ®åºè®°å½å½åçæ¬ä¹ä¸º 2 ï¼ä¸æ»¡è¶³ â æäº¤çæ¬å¿
é¡»çäºå½åçæ¬æè½æ§è¡æ´æ° â çä¹è§éçç¥ï¼å æ¤ï¼æä½å B çæäº¤è¢«é©³åã
è¿æ ·å°±é¿å
äºæä½å B ç¨åºäº `version`=1 çæ§æ°æ®ä¿®æ¹çç»æè¦çæä½å A çæä½ç»æçå¯è½ã
#### CAS ç®æ³
CAS çå
¨ç§°æ¯ **Compare And Swapï¼æ¯è¾ä¸äº¤æ¢ï¼** ï¼ç¨äºå®ç°ä¹è§éï¼è¢«å¹¿æ³åºç¨äºåå¤§æ¡æ¶ä¸ãCAS çææ³å¾ç®åï¼å°±æ¯ç¨ä¸ä¸ªé¢æå¼åè¦æ´æ°çåéå¼è¿è¡æ¯è¾ï¼ä¸¤å¼ç¸çæä¼è¿è¡æ´æ°ã
CAS æ¯ä¸ä¸ªååæä½ï¼åºå±ä¾èµäºä¸æ¡ CPU çååæä»¤ã
> **ååæä½** 峿å°ä¸å¯æåçæä½ï¼ä¹å°±æ¯è¯´æä½ä¸æ¦å¼å§ï¼å°±ä¸è½è¢«ææï¼ç´å°æä½å®æã
CAS æ¶åå°ä¸ä¸ªæä½æ°ï¼
- **V**ï¼è¦æ´æ°çåéå¼(Var)
- **E**ï¼é¢æå¼(Expected)
- **N**ï¼æåå
¥çæ°å¼(New)
å½ä¸ä»
å½ V çå¼çäº E æ¶ï¼CAS éè¿ååæ¹å¼ç¨æ°å¼ N æ¥æ´æ° V çå¼ã妿ä¸çï¼è¯´æå·²ç»æå
¶å®çº¿ç¨æ´æ°äº Vï¼åå½åçº¿ç¨æ¾å¼æ´æ°ã
**举ä¸ä¸ªç®åçä¾å**ï¼çº¿ç¨ A è¦ä¿®æ¹åé i çå¼ä¸º 6ï¼i åå¼ä¸º 1ï¼V = 1ï¼E=1ï¼N=6ï¼å设ä¸åå¨ ABA é®é¢ï¼ã
1. i ä¸ 1 è¿è¡æ¯è¾ï¼å¦æç¸çï¼ åè¯´ææ²¡è¢«å
¶ä»çº¿ç¨ä¿®æ¹ï¼å¯ä»¥è¢«è®¾ç½®ä¸º 6 ã
2. i ä¸ 1 è¿è¡æ¯è¾ï¼å¦æä¸ç¸çï¼å说æè¢«å
¶ä»çº¿ç¨ä¿®æ¹ï¼å½åçº¿ç¨æ¾å¼æ´æ°ï¼CAS æä½å¤±è´¥ã
å½å¤ä¸ªçº¿ç¨åæ¶ä½¿ç¨ CAS æä½ä¸ä¸ªåéæ¶ï¼åªæä¸ä¸ªä¼èåºï¼å¹¶æåæ´æ°ï¼å
¶ä½åä¼å¤±è´¥ï¼ä½å¤±è´¥ç线ç¨å¹¶ä¸ä¼è¢«æèµ·ï¼ä»
æ¯è¢«åç¥å¤±è´¥ï¼å¹¶ä¸å
è®¸åæ¬¡å°è¯ï¼å½ç¶ä¹å
许失败ççº¿ç¨æ¾å¼æä½ã
Java è¯è¨å¹¶æ²¡æç´æ¥å®ç° CASï¼CAS ç¸å
³çå®ç°æ¯éè¿ C++ å
èæ±ç¼çå½¢å¼å®ç°çï¼JNI è°ç¨ï¼ãå æ¤ï¼ CAS çå
·ä½å®ç°åæä½ç³»ç»ä»¥å CPU 齿å
³ç³»ã
`sun.misc`å
ä¸ç`Unsafe`ç±»æä¾äº`compareAndSwapObject`ã`compareAndSwapInt`ã`compareAndSwapLong`æ¹æ³æ¥å®ç°ç对`Object`ã`int`ã`long`ç±»åç CAS æä½
```java
/**
* CAS
* @param o å
å«è¦ä¿®æ¹fieldç对象
* @param offset å¯¹è±¡ä¸æfieldçåç§»é
* @param expected ææå¼
* @param update æ´æ°å¼
* @return true | false
*/
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object update);
public final native boolean compareAndSwapInt(Object o, long offset, int expected,int update);
public final native boolean compareAndSwapLong(Object o, long offset, long expected, long update);
```
å
³äº `Unsafe` ç±»ç详ç»ä»ç»å¯ä»¥çè¿ç¯æç« ï¼[Java éæ³ç±» Unsafe 详解 - JavaGuide - 2022](https://javaguide.cn/java/basis/unsafe.html) ã
### Java ä¸ CAS æ¯å¦ä½å®ç°çï¼
å¨ Java ä¸ï¼å®ç° CASï¼Compare-And-Swap, æ¯è¾å¹¶äº¤æ¢ï¼æä½çä¸ä¸ªå
³é®ç±»æ¯`Unsafe`ã
`Unsafe`ç±»ä½äº`sun.misc`å
ä¸ï¼æ¯ä¸ä¸ªæä¾ä½çº§å«ãä¸å®å
¨æä½çç±»ãç±äºå
¶å¼ºå¤§çåè½åæ½å¨çå±é©æ§ï¼å®é常ç¨äº JVM å
鍿ä¸äºéè¦æé«æ§è½ååºå±è®¿é®çåºä¸ï¼è䏿¨èæ®éå¼åè
å¨åºç¨ç¨åºä¸ä½¿ç¨ãå
³äº `Unsafe`ç±»ç详ç»ä»ç»ï¼å¯ä»¥é
读è¿ç¯æç« ï¼ð[Java éæ³ç±» Unsafe 详解](https://javaguide.cn/java/basis/unsafe.html)ã
`sun.misc`å
ä¸ç`Unsafe`ç±»æä¾äº`compareAndSwapObject`ã`compareAndSwapInt`ã`compareAndSwapLong`æ¹æ³æ¥å®ç°ç对`Object`ã`int`ã`long`ç±»åç CAS æä½ï¼
```java
/**
* 以å忹弿´æ°å¯¹è±¡å段çå¼ã
*
* @param o è¦æä½ç对象
* @param offset å¯¹è±¡åæ®µçå
ååç§»é
* @param expected ææçæ§å¼
* @param x è¦è®¾ç½®çæ°å¼
* @return 妿å¼è¢«æåæ´æ°ï¼åè¿å trueï¼å¦åè¿å false
*/
boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
/**
* 以å忹弿´æ° int ç±»åçå¯¹è±¡åæ®µçå¼ã
*/
boolean compareAndSwapInt(Object o, long offset, int expected, int x);
/**
* 以å忹弿´æ° long ç±»åçå¯¹è±¡åæ®µçå¼ã
*/
boolean compareAndSwapLong(Object o, long offset, long expected, long x);
```
`Unsafe`ç±»ä¸ç CAS æ¹æ³æ¯`native`æ¹æ³ã`native`å
³é®å表æè¿äºæ¹æ³æ¯ç¨æ¬å°ä»£ç ï¼éå¸¸æ¯ C æ C++ï¼å®ç°çï¼è䏿¯ç¨ Java å®ç°çãè¿äºæ¹æ³ç´æ¥è°ç¨åºå±ç硬件æä»¤æ¥å®ç°ååæä½ãä¹å°±æ¯è¯´ï¼Java è¯è¨å¹¶æ²¡æç´æ¥ç¨ Java å®ç° CASï¼èæ¯éè¿ C++ å
èæ±ç¼çå½¢å¼å®ç°çï¼éè¿ JNI è°ç¨ï¼ãå æ¤ï¼CAS çå
·ä½å®ç°ä¸æä½ç³»ç»ä»¥å CPU å¯åç¸å
³ã
`java.util.concurrent.atomic` å
æä¾äºä¸äºç¨äºååæä½çç±»ãè¿äºç±»å©ç¨åºå±çååæä»¤ï¼ç¡®ä¿å¨å¤çº¿ç¨ç¯å¢ä¸çæä½æ¯çº¿ç¨å®å
¨çã

å
³äºè¿äº Atomic ååç±»çä»ç»å使ç¨ï¼å¯ä»¥é
读è¿ç¯æç« ï¼[Atomic ååç±»æ»ç»](https://javaguide.cn/java/concurrent/atomic-classes.html)ã
`AtomicInteger`æ¯ Java çååç±»ä¹ä¸ï¼ä¸»è¦ç¨äºå¯¹ `int` ç±»åçåéè¿è¡ååæä½ï¼å®å©ç¨`Unsafe`ç±»æä¾çä½çº§å«ååæä½æ¹æ³å®ç°æ éç线ç¨å®å
¨æ§ã
ä¸é¢ï¼æä»¬éè¿è§£è¯»`AtomicInteger`çæ ¸å¿æºç ï¼JDK1.8ï¼ï¼æ¥è¯´æ Java å¦ä½ä½¿ç¨`Unsafe`ç±»çæ¹æ³æ¥å®ç°ååæä½ã
`AtomicInteger`æ ¸å¿æºç å¦ä¸ï¼
```java
// è·å Unsafe å®ä¾
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
// è·åâvalueâåæ®µå¨AtomicIntegerç±»ä¸çå
ååç§»é
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// ç¡®ä¿âvalueâåæ®µçå¯è§æ§
private volatile int value;
// 妿å½åå¼çäºé¢æå¼ï¼åååå°å°å¼è®¾ç½®ä¸ºnewValue
// ä½¿ç¨ Unsafe#compareAndSwapInt æ¹æ³è¿è¡CASæä½
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// ååå°å°å½åå¼å delta å¹¶è¿åæ§å¼
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
// ååå°å°å½åå¼å 1 å¹¶è¿åå ä¹åçå¼ï¼æ§å¼ï¼
// ä½¿ç¨ Unsafe#getAndAddInt æ¹æ³è¿è¡CASæä½ã
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// ååå°å°å½åå¼å 1 å¹¶è¿ååä¹åçå¼ï¼æ§å¼ï¼
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
```
`Unsafe#getAndAddInt`æºç ï¼
```java
// ååå°è·åå¹¶å¢å æ´æ°å¼
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
// 以 volatile æ¹å¼è·å对象 o å¨å
ååç§»é offset å¤çæ´æ°å¼
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
// è¿åæ§å¼
return v;
}
```
å¯ä»¥çå°ï¼`getAndAddInt` 使ç¨äº `do-while` 循ç¯ï¼å¨`compareAndSwapInt`æä½å¤±è´¥æ¶ï¼ä¼ä¸æéè¯ç´å°æåãä¹å°±æ¯è¯´ï¼`getAndAddInt`æ¹æ³ä¼éè¿ `compareAndSwapInt` æ¹æ³æ¥å°è¯æ´æ° `value` çå¼ï¼å¦ææ´æ°å¤±è´¥ï¼å½åå¼å¨æ¤æé´è¢«å
¶ä»çº¿ç¨ä¿®æ¹ï¼ï¼å®ä¼éæ°è·åå½åå¼å¹¶å次å°è¯æ´æ°ï¼ç´å°æä½æåã
ç±äº CAS æä½å¯è½ä¼å 为并åå²çªè失败ï¼å æ¤é常ä¼ä¸`while`å¾ªç¯æé
使ç¨ï¼å¨å¤±è´¥å䏿éè¯ï¼ç´å°æä½æåãè¿å°±æ¯ **èªæéæºå¶** ã
### CAS ç®æ³åå¨åªäºé®é¢ï¼
ABA é®é¢æ¯ CAS ç®æ³æå¸¸è§çé®é¢ã
#### ABA é®é¢
妿ä¸ä¸ªåé V 忬¡è¯»åçæ¶åæ¯ A å¼ï¼å¹¶ä¸å¨åå¤èµå¼çæ¶åæ£æ¥å°å®ä»ç¶æ¯ A å¼ï¼é£æä»¬å°±è½è¯´æå®ç弿²¡æè¢«å
¶ä»çº¿ç¨ä¿®æ¹è¿äºåï¼å¾ææ¾æ¯ä¸è½çï¼å 为å¨è¿æ®µæ¶é´å®çå¼å¯è½è¢«æ¹ä¸ºå
¶ä»å¼ï¼ç¶ååæ¹å Aï¼é£ CAS æä½å°±ä¼è¯¯è®¤ä¸ºå®ä»æ¥æ²¡æè¢«ä¿®æ¹è¿ãè¿ä¸ªé®é¢è¢«ç§°ä¸º CAS æä½ç **"ABA"é®é¢ã**
ABA é®é¢çè§£å³æè·¯æ¯å¨åéåé¢è¿½å ä¸**çæ¬å·æè
æ¶é´æ³**ãJDK 1.5 以åç `AtomicStampedReference` 类就æ¯ç¨æ¥è§£å³ ABA é®é¢çï¼å
¶ä¸ç `compareAndSet()` æ¹æ³å°±æ¯é¦å
æ£æ¥å½åå¼ç¨æ¯å¦çäºé¢æå¼ç¨ï¼å¹¶ä¸å½åæ å¿æ¯å¦çäºé¢ææ å¿ï¼å¦æå
¨é¨ç¸çï¼å以ååæ¹å¼å°è¯¥å¼ç¨å该æ å¿çå¼è®¾ç½®ä¸ºç»å®çæ´æ°å¼ã
```java
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
```
#### å¾ªç¯æ¶é´é¿å¼é大
CAS ç»å¸¸ä¼ç¨å°èªææä½æ¥è¿è¡éè¯ï¼ä¹å°±æ¯ä¸æåå°±ä¸ç´å¾ªç¯æ§è¡ç´å°æåãå¦æé¿æ¶é´ä¸æåï¼ä¼ç» CPU 带æ¥éå¸¸å¤§çæ§è¡å¼éã
妿 JVM è½å¤æ¯æå¤ç卿ä¾ç`pause`æä»¤ï¼é£ä¹èªææä½çæçå°æææåã`pause`æä»¤æä¸¤ä¸ªéè¦ä½ç¨ï¼
1. **å»¶è¿æµæ°´çº¿æ§è¡æä»¤**ï¼`pause`æä»¤å¯ä»¥å»¶è¿æä»¤çæ§è¡ï¼ä»èåå° CPU çèµæºæ¶èãå
·ä½çå»¶è¿æ¶é´åå³äºå¤çå¨çå®ç°çæ¬ï¼å¨æäºå¤çå¨ä¸ï¼å»¶è¿æ¶é´å¯è½ä¸ºé¶ã
2. **é¿å
å
å顺åºå²çª**ï¼å¨éåºå¾ªç¯æ¶ï¼`pause`æä»¤å¯ä»¥é¿å
ç±äºå
å顺åºå²çªè导è´ç CPU æµæ°´çº¿è¢«æ¸
空ï¼ä»èæé« CPU çæ§è¡æçã
#### åªè½ä¿è¯ä¸ä¸ªå
±äº«åéçååæä½
CAS æä½ä»
è½å¯¹å个å
±äº«åéææãå½éè¦æä½å¤ä¸ªå
±äº«åéæ¶ï¼CAS å°±æ¾å¾æ è½ä¸ºåãä¸è¿ï¼ä» JDK 1.5 å¼å§ï¼Java æä¾äº`AtomicReference`ç±»ï¼è¿ä½¿å¾æä»¬è½å¤ä¿è¯å¼ç¨å¯¹è±¡ä¹é´çååæ§ãéè¿å°å¤ä¸ªåéå°è£
å¨ä¸ä¸ªå¯¹è±¡ä¸ï¼æä»¬å¯ä»¥ä½¿ç¨`AtomicReference`æ¥æ§è¡ CAS æä½ã
é¤äº `AtomicReference` è¿ç§æ¹å¼ä¹å¤ï¼è¿å¯ä»¥å©ç¨å 鿥ä¿è¯ã
## synchronized å
³é®å
### synchronized æ¯ä»ä¹ï¼æä»ä¹ç¨ï¼
`synchronized` æ¯ Java ä¸çä¸ä¸ªå
³é®åï¼ç¿»è¯æä¸ææ¯åæ¥çææï¼ä¸»è¦è§£å³çæ¯å¤ä¸ªçº¿ç¨ä¹é´è®¿é®èµæºç忥æ§ï¼å¯ä»¥ä¿è¯è¢«å®ä¿®é¥°çæ¹æ³æè
代ç åå¨ä»»ææ¶å»åªè½æä¸ä¸ªçº¿ç¨æ§è¡ã
å¨ Java æ©æçæ¬ä¸ï¼`synchronized` å±äº **éé级é**ï¼æçä½ä¸ãè¿æ¯å 为çè§å¨éï¼monitorï¼æ¯ä¾èµäºåºå±çæä½ç³»ç»ç `Mutex Lock` æ¥å®ç°çï¼Java ççº¿ç¨æ¯æ å°å°æä½ç³»ç»çåç线ç¨ä¹ä¸çãå¦æè¦æèµ·æè
å¤éä¸ä¸ªçº¿ç¨ï¼é½éè¦æä½ç³»ç»å¸®å¿å®æï¼èæä½ç³»ç»å®ç°çº¿ç¨ä¹é´ç忢æ¶éè¦ä»ç¨æ·æè½¬æ¢å°å
æ ¸æï¼è¿ä¸ªç¶æä¹é´ç转æ¢éè¦ç¸å¯¹æ¯è¾é¿çæ¶é´ï¼æ¶é´ææ¬ç¸å¯¹è¾é«ã
ä¸è¿ï¼å¨ Java 6 ä¹åï¼ `synchronized` å¼å
¥äºå¤§éçä¼åå¦èªæéãéåºæ§èªæéãéæ¶é¤ãéç²åãååéãè½»é级éçææ¯æ¥åå°éæä½çå¼éï¼è¿äºä¼å让 `synchronized` éçæçæåäºå¾å¤ãå æ¤ï¼ `synchronized` è¿æ¯å¯ä»¥å¨å®é
项ç®ä¸ä½¿ç¨çï¼å JDK æºç ãå¾å¤å¼æºæ¡æ¶é½å¤§é使ç¨äº `synchronized` ã
å
³äºååéå¤è¡¥å
ä¸ç¹ï¼ç±äºååéå¢å äº JVM ç夿æ§ï¼åæ¶ä¹å¹¶æ²¡æä¸ºææåºç¨é½å¸¦æ¥æ§è½æåãå æ¤ï¼å¨ JDK15 ä¸ï¼ååé被é»è®¤å
³éï¼ä»ç¶å¯ä»¥ä½¿ç¨ `-XX:+UseBiasedLocking` å¯ç¨ååéï¼ï¼å¨ JDK18 ä¸ï¼ååéå·²ç»è¢«å½»åºåºå¼ï¼æ æ³éè¿å½ä»¤è¡æå¼ï¼ã
### å¦ä½ä½¿ç¨ synchronizedï¼
`synchronized` å
³é®åçä½¿ç¨æ¹å¼ä¸»è¦æä¸é¢ 3 ç§ï¼
1. 修饰å®ä¾æ¹æ³
2. ä¿®é¥°éææ¹æ³
3. 修饰代ç å
**1ã修饰å®ä¾æ¹æ³** ï¼éå½å对象å®ä¾ï¼
ç»å½å对象å®ä¾å éï¼è¿å
¥åæ¥ä»£ç åè¦è·å¾ **å½å对象å®ä¾çé** ã
```java
synchronized void method() {
//ä¸å¡ä»£ç
}
```
**2ãä¿®é¥°éææ¹æ³** ï¼éå½åç±»ï¼
ç»å½åç±»å éï¼ä¼ä½ç¨äºç±»çææå¯¹è±¡å®ä¾ ï¼è¿å
¥åæ¥ä»£ç åè¦è·å¾ **å½å class çé**ã
è¿æ¯å ä¸ºéææåä¸å±äºä»»ä½ä¸ä¸ªå®ä¾å¯¹è±¡ï¼å½æ´ä¸ªç±»ææï¼ä¸ä¾èµäºç±»çç¹å®å®ä¾ï¼è¢«ç±»çææå®ä¾å
±äº«ã
```java
synchronized static void method() {
//ä¸å¡ä»£ç
}
```
éæ `synchronized` æ¹æ³åééæ `synchronized` æ¹æ³ä¹é´çè°ç¨äºæ¥ä¹ï¼ä¸äºæ¥ï¼å¦æä¸ä¸ªçº¿ç¨ A è°ç¨ä¸ä¸ªå®ä¾å¯¹è±¡çééæ `synchronized` æ¹æ³ï¼èçº¿ç¨ B éè¦è°ç¨è¿ä¸ªå®ä¾å¯¹è±¡æå±ç±»çéæ `synchronized` æ¹æ³ï¼æ¯å
许çï¼ä¸ä¼åçäºæ¥ç°è±¡ï¼å 为访é®éæ `synchronized` æ¹æ³å ç¨ç鿝å½åç±»çéï¼è访é®ééæ `synchronized` æ¹æ³å ç¨ç鿝å½åå®ä¾å¯¹è±¡éã
**3ã修饰代ç å** ï¼éæå®å¯¹è±¡/ç±»ï¼
对æ¬å·éæå®ç对象/ç±»å éï¼
- `synchronized(object)` 表示è¿å
¥åæ¥ä»£ç ååè¦è·å¾ **ç»å®å¯¹è±¡çé**ã
- `synchronized(ç±».class)` 表示è¿å
¥åæ¥ä»£ç ååè¦è·å¾ **ç»å® Class çé**
```java
synchronized(this) {
//ä¸å¡ä»£ç
}
```
**æ»ç»ï¼**
- `synchronized` å
³é®åå å° `static` éææ¹æ³å `synchronized(class)` 代ç åä¸é½æ¯æ¯ç» Class ç±»ä¸éï¼
- `synchronized` å
³é®åå å°å®ä¾æ¹æ³ä¸æ¯ç»å¯¹è±¡å®ä¾ä¸éï¼
- å°½éä¸è¦ä½¿ç¨ `synchronized(String a)` å 为 JVM ä¸ï¼åç¬¦ä¸²å¸¸éæ± å
·æç¼ååè½ã
### æé æ¹æ³å¯ä»¥ç¨ synchronized 修饰ä¹ï¼
æé æ¹æ³ä¸è½ä½¿ç¨ synchronized å
³é®å修饰ãä¸è¿ï¼å¯ä»¥å¨æé æ¹æ³å
é¨ä½¿ç¨ synchronized 代ç åã
å¦å¤ï¼æé æ¹æ³æ¬èº«æ¯çº¿ç¨å®å
¨çï¼ä½å¦æå¨æé æ¹æ³ä¸æ¶åå°å
±äº«èµæºçæä½ï¼å°±éè¦éåéå½çåæ¥æªæ½æ¥ä¿è¯æ´ä¸ªæé è¿ç¨ç线ç¨å®å
¨ã
### âï¸synchronized åºå±åçäºè§£åï¼
synchronized å
³é®ååºå±åçå±äº JVM å±é¢çä¸è¥¿ã
#### synchronized 忥è¯å¥åçæ
åµ
```java
public class SynchronizedDemo {
public void method() {
synchronized (this) {
System.out.println("synchronized 代ç å");
}
}
}
```
éè¿ JDK èªå¸¦ç `javap` å½ä»¤æ¥ç `SynchronizedDemo` ç±»çç¸å
³åèç ä¿¡æ¯ï¼é¦å
忢å°ç±»ç对åºç®å½æ§è¡ `javac SynchronizedDemo.java` å½ä»¤çæç¼è¯åç .class æä»¶ï¼ç¶åæ§è¡`javap -c -s -v -l SynchronizedDemo.class`ã

ä»ä¸é¢æä»¬å¯ä»¥çåºï¼**`synchronized` 忥è¯å¥åçå®ç°ä½¿ç¨çæ¯ `monitorenter` å `monitorexit` æä»¤ï¼å
¶ä¸ `monitorenter` æä»¤æå忥代ç åçå¼å§ä½ç½®ï¼`monitorexit` æä»¤åææåæ¥ä»£ç åçç»æä½ç½®ã**
ä¸é¢çåèç ä¸å
å«ä¸ä¸ª `monitorenter` æä»¤ä»¥å两个 `monitorexit` æä»¤ï¼è¿æ¯ä¸ºäºä¿è¯éå¨åæ¥ä»£ç åä»£ç æ£å¸¸æ§è¡ä»¥ååºç°å¼å¸¸çè¿ä¸¤ç§æ
åµä¸é½è½è¢«æ£ç¡®éæ¾ã
彿§è¡ `monitorenter` æä»¤æ¶ï¼çº¿ç¨è¯å¾è·åéä¹å°±æ¯è·å **对象çè§å¨ `monitor`** çæææã
> å¨ Java èææº(HotSpot)ä¸ï¼Monitor æ¯åºäº C++å®ç°çï¼ç±[ObjectMonitor](https://github.com/openjdk-mirror/jdk7u-hotspot/blob/50bdefc3afe944ca74c3093e7448d6b889cd20d1/src/share/vm/runtime/objectMonitor.cpp)å®ç°çãæ¯ä¸ªå¯¹è±¡ä¸é½å
ç½®äºä¸ä¸ª `ObjectMonitor`对象ã
>
> å¦å¤ï¼`wait/notify`çæ¹æ³ä¹ä¾èµäº`monitor`对象ï¼è¿å°±æ¯ä¸ºä»ä¹åªæå¨åæ¥çåæè
æ¹æ³ä¸æè½è°ç¨`wait/notify`çæ¹æ³ï¼å¦å伿åº`java.lang.IllegalMonitorStateException`çå¼å¸¸çåå ã
卿§è¡`monitorenter`æ¶ï¼ä¼å°è¯è·å对象çéï¼å¦æéç计æ°å¨ä¸º 0 å表示éå¯ä»¥è¢«è·åï¼è·ååå°é计æ°å¨è®¾ä¸º 1 ä¹å°±æ¯å 1ã

对象éçæ¥æè
çº¿ç¨æå¯ä»¥æ§è¡ `monitorexit` æä»¤æ¥éæ¾éã卿§è¡ `monitorexit` æä»¤åï¼å°é计æ°å¨è®¾ä¸º 0ï¼è¡¨æéè¢«éæ¾ï¼å
¶ä»çº¿ç¨å¯ä»¥å°è¯è·åéã

妿è·å对象é失败ï¼é£å½å线ç¨å°±è¦é»å¡çå¾
ï¼ç´å°é被å¦å¤ä¸ä¸ªçº¿ç¨éæ¾ä¸ºæ¢ã
#### synchronized ä¿®é¥°æ¹æ³çæ
åµ
```java
public class SynchronizedDemo2 {
public synchronized void method() {
System.out.println("synchronized æ¹æ³");
}
}
```

`synchronized` ä¿®é¥°çæ¹æ³å¹¶æ²¡æ `monitorenter` æä»¤å `monitorexit` æä»¤ï¼åè代ä¹çæ¯ `ACC_SYNCHRONIZED` æ è¯ï¼è¯¥æ è¯ææäºè¯¥æ¹æ³æ¯ä¸ä¸ªåæ¥æ¹æ³ãJVM éè¿è¯¥ `ACC_SYNCHRONIZED` è®¿é®æ å¿æ¥è¾¨å«ä¸ä¸ªæ¹æ³æ¯å¦å£°æä¸ºåæ¥æ¹æ³ï¼ä»èæ§è¡ç¸åºç忥è°ç¨ã
妿æ¯å®ä¾æ¹æ³ï¼JVM ä¼å°è¯è·åå®ä¾å¯¹è±¡çéã妿æ¯éææ¹æ³ï¼JVM ä¼å°è¯è·åå½å class çéã
#### æ»ç»
`synchronized` 忥è¯å¥åçå®ç°ä½¿ç¨çæ¯ `monitorenter` å `monitorexit` æä»¤ï¼å
¶ä¸ `monitorenter` æä»¤æå忥代ç åçå¼å§ä½ç½®ï¼`monitorexit` æä»¤åææåæ¥ä»£ç åçç»æä½ç½®ã
`synchronized` ä¿®é¥°çæ¹æ³å¹¶æ²¡æ `monitorenter` æä»¤å `monitorexit` æä»¤ï¼åè代ä¹çæ¯ `ACC_SYNCHRONIZED` æ è¯ï¼è¯¥æ è¯ææäºè¯¥æ¹æ³æ¯ä¸ä¸ªåæ¥æ¹æ³ã
**ä¸è¿ï¼ä¸¤è
çæ¬è´¨é½æ¯å¯¹å¯¹è±¡çè§å¨ monitor çè·åã**
ç¸å
³æ¨èï¼[Java éä¸çº¿ç¨çé£äºäº - æèµææ¯å¢é](https://tech.youzan.com/javasuo-yu-xian-cheng-de-na-xie-shi/) ã
ð§ð» è¿é¶ä¸ä¸ï¼å¦æä½åçå°ä¼ä¼´å¯ä»¥æ½æ¶é´è¯¦ç»ç ç©¶ä¸ä¸å¯¹è±¡çè§å¨ `monitor`ã
### JDK1.6 ä¹åç synchronized åºå±åäºåªäºä¼åï¼éå级åçäºè§£åï¼
å¨ Java 6 ä¹åï¼ `synchronized` å¼å
¥äºå¤§éçä¼åå¦èªæéãéåºæ§èªæéãéæ¶é¤ãéç²åãååéãè½»é级éçææ¯æ¥åå°éæä½çå¼éï¼è¿äºä¼å让 `synchronized` éçæçæåäºå¾å¤ï¼JDK18 ä¸ï¼ååéå·²ç»è¢«å½»åºåºå¼ï¼åé¢å·²ç»æå°è¿äºï¼ã
é主è¦åå¨åç§ç¶æï¼ä¾æ¬¡æ¯ï¼æ éç¶æãååéç¶æãè½»é级éç¶æãéé级éç¶æï¼ä»ä»¬ä¼éçç«äºçæ¿çè鿏åçº§ãæ³¨æéå¯ä»¥å级ä¸å¯é级ï¼è¿ç§çç¥æ¯ä¸ºäºæé«è·å¾éåéæ¾éçæçã
`synchronized` éå级æ¯ä¸ä¸ªæ¯è¾å¤æçè¿ç¨ï¼é¢è¯ä¹å¾å°é®å°ï¼å¦æä½ æ³è¦è¯¦ç»äºè§£çè¯ï¼å¯ä»¥ççè¿ç¯æç« ï¼[æµ
æ synchronized éå级çåçä¸å®ç°](https://www.cnblogs.com/star95/p/17542850.html)ã
### synchronized çååé为ä»ä¹è¢«åºå¼äºï¼
Open JDK 宿¹å£°æï¼[JEP 374: Deprecate and Disable Biased Locking](https://openjdk.org/jeps/374)
å¨ JDK15 ä¸ï¼ååé被é»è®¤å
³éï¼ä»ç¶å¯ä»¥ä½¿ç¨ `-XX:+UseBiasedLocking` å¯ç¨ååéï¼ï¼å¨ JDK18 ä¸ï¼ååéå·²ç»è¢«å½»åºåºå¼ï¼æ æ³éè¿å½ä»¤è¡æå¼ï¼ã
å¨å®æ¹å£°æä¸ï¼ä¸»è¦åå æä¸¤ä¸ªæ¹é¢ï¼
- **æ§è½æ¶ç䏿æ¾ï¼**
åå鿝 HotSpot èææºçä¸é¡¹ä¼åææ¯ï¼å¯ä»¥æåå线ç¨å¯¹åæ¥ä»£ç åçè®¿é®æ§è½ã
åçäºååéçåºç¨ç¨åºé常使ç¨äºæ©æç Java éå APIï¼ä¾å¦ HashTableãVectorï¼å¨è¿äºéåç±»ä¸éè¿ synchronized æ¥æ§å¶åæ¥ï¼è¿æ ·å¨å线ç¨é¢ç¹è®¿é®æ¶ï¼éè¿ååéä¼åå°åæ¥å¼éã
éç JDK çåå±ï¼åºç°äº ConcurrentHashMap 髿§è½çéåç±»ï¼å¨éåç±»å
é¨è¿è¡äºè®¸å¤æ§è½ä¼åï¼æ¤æ¶ååé带æ¥çæ§è½æ¶ç就䏿æ¾äºã
ååéä»
ä»
å¨å线ç¨è®¿é®åæ¥ä»£ç åçåºæ¯ä¸å¯ä»¥è·å¾æ§è½æ¶çã
妿åå¨å¤çº¿ç¨ç«äºï¼å°±éè¦ **æ¤éååé** ï¼è¿ä¸ªæä½çæ§è½å¼éæ¯æ¯è¾æè´µçãååéçæ¤ééè¦çå¾
è¿å
¥å°å
¨å±å®å
¨ç¹ï¼safe pointï¼ï¼è¯¥ç¶æä¸ææçº¿ç¨é½æ¯æåçï¼æ¤æ¶å»æ£æ¥çº¿ç¨ç¶æå¹¶è¿è¡ååéçæ¤éã
- **JVM å
é¨ä»£ç ç»´æ¤ææ¬å¤ªé«ï¼**
ååéå°è®¸å¤å¤æä»£ç å¼å
¥å°åæ¥åç³»ç»ï¼å¹¶ä¸å¯¹å
¶ä»ç HotSpot ç»ä»¶ä¹å
·æä¾µå
¥æ§ãè¿ç§å¤ææ§ä¸ºç解代ç ãç³»ç»éæå¸¦æ¥äºå°é¾ï¼å æ¤ï¼ OpenJDK 宿¹å¸æç¦ç¨ãåºå¼å¹¶å é¤ååéã
### âï¸synchronized å volatile æä»ä¹åºå«ï¼
`synchronized` å
³é®åå `volatile` å
³é®åæ¯ä¸¤ä¸ªäºè¡¥çåå¨ï¼è䏿¯å¯¹ç«çåå¨ï¼
- `volatile` å
³é®åæ¯çº¿ç¨åæ¥çè½»é级å®ç°ï¼æä»¥ `volatile`æ§è½è¯å®æ¯`synchronized`å
³é®åè¦å¥½ ã使¯ `volatile` å
³é®ååªè½ç¨äºåéè `synchronized` å
³é®åå¯ä»¥ä¿®é¥°æ¹æ³ä»¥å代ç å ã
- `volatile` å
³é®åè½ä¿è¯æ°æ®çå¯è§æ§ï¼ä½ä¸è½ä¿è¯æ°æ®çååæ§ã`synchronized` å
³é®å两è
é½è½ä¿è¯ã
- `volatile`å
³é®å主è¦ç¨äºè§£å³åéå¨å¤ä¸ªçº¿ç¨ä¹é´çå¯è§æ§ï¼è `synchronized` å
³é®åè§£å³çæ¯å¤ä¸ªçº¿ç¨ä¹é´è®¿é®èµæºç忥æ§ã
## ReentrantLock
### ReentrantLock æ¯ä»ä¹ï¼
`ReentrantLock` å®ç°äº `Lock` æ¥å£ï¼æ¯ä¸ä¸ªå¯éå
¥ä¸ç¬å å¼çéï¼å `synchronized` å
³é®å类似ãä¸è¿ï¼`ReentrantLock` æ´çµæ´»ãæ´å¼ºå¤§ï¼å¢å äºè½®è¯¢ãè¶
æ¶ã䏿ãå
¬å¹³éåéå
¬å¹³éçé«çº§åè½ã
```java
public class ReentrantLock implements Lock, java.io.Serializable {}
```
`ReentrantLock` é颿ä¸ä¸ªå
é¨ç±» `Sync`ï¼`Sync` ç»§æ¿ AQSï¼`AbstractQueuedSynchronizer`ï¼ï¼æ·»å éåéæ¾éç大é¨åæä½å®é
ä¸é½æ¯å¨ `Sync` ä¸å®ç°çã`Sync` æå
¬å¹³é `FairSync` åéå
¬å¹³é `NonfairSync` 两个åç±»ã

`ReentrantLock` é»è®¤ä½¿ç¨éå
¬å¹³éï¼ä¹å¯ä»¥éè¿æé 卿¥æ¾å¼çæå®ä½¿ç¨å
¬å¹³éã
```java
// ä¼ å
¥ä¸ä¸ª boolean å¼ï¼true æ¶ä¸ºå
¬å¹³éï¼false æ¶ä¸ºéå
¬å¹³é
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
```
ä»ä¸é¢çå
容å¯ä»¥çåºï¼ `ReentrantLock` çåºå±å°±æ¯ç± AQS æ¥å®ç°çãå
³äº AQS çç¸å
³å
容æ¨èé
读 [AQS 详解](https://javaguide.cn/java/concurrent/aqs.html) è¿ç¯æç« ã
### å
¬å¹³éåéå
¬å¹³éæä»ä¹åºå«ï¼
- **å
¬å¹³é** : éè¢«éæ¾ä¹åï¼å
ç³è¯·ç线ç¨å
å¾å°éãæ§è½è¾å·®ä¸äºï¼å 为å
¬å¹³é为äºä¿è¯æ¶é´ä¸çç»å¯¹é¡ºåºï¼ä¸ä¸æåæ¢æ´é¢ç¹ã
- **éå
¬å¹³é**ï¼éè¢«éæ¾ä¹åï¼åç³è¯·ç线ç¨å¯è½ä¼å
è·åå°éï¼æ¯éæºæè
æç
§å
¶ä»ä¼å
级æåºçãæ§è½æ´å¥½ï¼ä½å¯è½ä¼å¯¼è´æäºçº¿ç¨æ°¸è¿æ æ³è·åå°éã
### âï¸synchronized å ReentrantLock æä»ä¹åºå«ï¼
#### 两è
齿¯å¯éå
¥é
**å¯éå
¥é** ä¹å«éå½éï¼æçæ¯çº¿ç¨å¯ä»¥å次è·åèªå·±çå
é¨éãæ¯å¦ä¸ä¸ªçº¿ç¨è·å¾äºæä¸ªå¯¹è±¡çéï¼æ¤æ¶è¿ä¸ªå¯¹è±¡éè¿æ²¡æéæ¾ï¼å½å
¶å次æ³è¦è·åè¿ä¸ªå¯¹è±¡çéçæ¶åè¿æ¯å¯ä»¥è·åçï¼å¦ææ¯ä¸å¯éå
¥éçè¯ï¼å°±ä¼é ææ»éã
JDK æä¾çææç°æç `Lock` å®ç°ç±»ï¼å
æ¬ `synchronized` å
³é®åé齿¯å¯éå
¥çã
å¨ä¸é¢ç代ç ä¸ï¼`method1()` å `method2()`é½è¢« `synchronized` å
³é®å修饰ï¼`method1()`è°ç¨äº`method2()`ã
```java
public class SynchronizedDemo {
public synchronized void method1() {
System.out.println("æ¹æ³1");
method2();
}
public synchronized void method2() {
System.out.println("æ¹æ³2");
}
}
```
ç±äº `synchronized`鿝å¯éå
¥çï¼åä¸ä¸ªçº¿ç¨å¨è°ç¨`method1()` æ¶å¯ä»¥ç´æ¥è·å¾å½å对象çéï¼æ§è¡ `method2()` çæ¶åå¯ä»¥å次è·åè¿ä¸ªå¯¹è±¡çéï¼ä¸ä¼äº§çæ»éé®é¢ãåå¦`synchronized`æ¯ä¸å¯éå
¥éçè¯ï¼ç±äºè¯¥å¯¹è±¡çé已被å½åçº¿ç¨æææä¸æ æ³éæ¾ï¼è¿å°±å¯¼è´çº¿ç¨å¨æ§è¡ `method2()`æ¶è·åé失败ï¼ä¼åºç°æ»éé®é¢ã
#### synchronized ä¾èµäº JVM è ReentrantLock ä¾èµäº API
`synchronized` æ¯ä¾èµäº JVM å®ç°çï¼å颿们ä¹è®²å°äº èææºå¢éå¨ JDK1.6 为 `synchronized` å
³é®åè¿è¡äºå¾å¤ä¼åï¼ä½æ¯è¿äºä¼å齿¯å¨èææºå±é¢å®ç°çï¼å¹¶æ²¡æç´æ¥æ´é²ç»æä»¬ã
`ReentrantLock` æ¯ JDK å±é¢å®ç°çï¼ä¹å°±æ¯ API å±é¢ï¼éè¦ lock() å unlock() æ¹æ³é
å try/finally è¯å¥åæ¥å®æï¼ï¼æä»¥æä»¬å¯ä»¥éè¿æ¥çå®çæºä»£ç ï¼æ¥ç宿¯å¦ä½å®ç°çã
#### ReentrantLock æ¯ synchronized å¢å äºä¸äºé«çº§åè½
ç¸æ¯`synchronized`ï¼`ReentrantLock`å¢å äºä¸äºé«çº§åè½ãä¸»è¦æ¥è¯´ä¸»è¦æä¸ç¹ï¼
- **çå¾
å¯ä¸æ** : `ReentrantLock`æä¾äºä¸ç§è½å¤ä¸æçå¾
éç线ç¨çæºå¶ï¼éè¿ `lock.lockInterruptibly()` æ¥å®ç°è¿ä¸ªæºå¶ãä¹å°±æ¯è¯´å½å线ç¨å¨çå¾
è·åéçè¿ç¨ä¸ï¼å¦æå
¶ä»çº¿ç¨ä¸æå½å线ç¨ã `interrupt()` ãï¼å½å线ç¨å°±ä¼æåº `InterruptedException` å¼å¸¸ï¼å¯ä»¥ææè¯¥å¼å¸¸è¿è¡ç¸åºå¤çã
- **å¯å®ç°å
¬å¹³é** : `ReentrantLock`å¯ä»¥æå®æ¯å
¬å¹³éè¿æ¯éå
¬å¹³éãè`synchronized`åªè½æ¯éå
¬å¹³éãæè°çå
¬å¹³éå°±æ¯å
çå¾
ç线ç¨å
è·å¾éã`ReentrantLock`é»è®¤æ
嵿¯éå
¬å¹³çï¼å¯ä»¥éè¿ `ReentrantLock`ç±»ç`ReentrantLock(boolean fair)`æé æ¹æ³æ¥æå®æ¯å¦æ¯å
¬å¹³çã
- **å¯å®ç°éæ©æ§éç¥ï¼éå¯ä»¥ç»å®å¤ä¸ªæ¡ä»¶ï¼**: `synchronized`å
³é®åä¸`wait()`å`notify()`/`notifyAll()`æ¹æ³ç¸ç»åå¯ä»¥å®ç°çå¾
/éç¥æºå¶ã`ReentrantLock`ç±»å½ç¶ä¹å¯ä»¥å®ç°ï¼ä½æ¯éè¦åå©äº`Condition`æ¥å£ä¸`newCondition()`æ¹æ³ã
- **æ¯æè¶
æ¶** ï¼`ReentrantLock` æä¾äº `tryLock(timeout)` çæ¹æ³ï¼å¯ä»¥æå®çå¾
è·åéçæé¿çå¾
æ¶é´ï¼å¦æè¶
è¿äºçå¾
æ¶é´ï¼å°±ä¼è·åé失败ï¼ä¸ä¼ä¸ç´çå¾
ã
å¦æä½ æ³ä½¿ç¨ä¸è¿°åè½ï¼é£ä¹éæ© `ReentrantLock` æ¯ä¸ä¸ªä¸éçéæ©ã
å
³äº `Condition`æ¥å£çè¡¥å
ï¼
> `Condition`æ¯ JDK1.5 ä¹åææçï¼å®å
·æå¾å¥½ççµæ´»æ§ï¼æ¯å¦å¯ä»¥å®ç°å¤è·¯éç¥åè½ä¹å°±æ¯å¨ä¸ä¸ª`Lock`对象ä¸å¯ä»¥å建å¤ä¸ª`Condition`å®ä¾ï¼å³å¯¹è±¡çè§å¨ï¼ï¼**线ç¨å¯¹è±¡å¯ä»¥æ³¨å卿å®ç`Condition`ä¸ï¼ä»èå¯ä»¥æéæ©æ§çè¿è¡çº¿ç¨éç¥ï¼å¨è°åº¦çº¿ç¨ä¸æ´å çµæ´»ã å¨ä½¿ç¨`notify()/notifyAll()`æ¹æ³è¿è¡éç¥æ¶ï¼è¢«éç¥ççº¿ç¨æ¯ç± JVM éæ©çï¼ç¨`ReentrantLock`ç±»ç»å`Condition`å®ä¾å¯ä»¥å®ç°âéæ©æ§éç¥â** ï¼è¿ä¸ªåè½é常éè¦ï¼è䏿¯ `Condition` æ¥å£é»è®¤æä¾çãè`synchronized`å
³é®åå°±ç¸å½äºæ´ä¸ª `Lock` 对象ä¸åªæä¸ä¸ª`Condition`å®ä¾ï¼ææç线ç¨é½æ³¨åå¨å®ä¸ä¸ªèº«ä¸ã妿æ§è¡`notifyAll()`æ¹æ³çè¯å°±ä¼éç¥ææå¤äºçå¾
ç¶æç线ç¨ï¼è¿æ ·ä¼é æå¾å¤§çæçé®é¢ãè`Condition`å®ä¾ç`signalAll()`æ¹æ³ï¼åªä¼å¤é注åå¨è¯¥`Condition`å®ä¾ä¸çææçå¾
线ç¨ã
å
³äº **çå¾
å¯ä¸æ** çè¡¥å
ï¼
> `lockInterruptibly()` ä¼è®©è·åéç线ç¨å¨é»å¡çå¾
çè¿ç¨ä¸å¯ä»¥ååºä¸æï¼å³å½å线ç¨å¨è·åéçæ¶åï¼åç°é被å
¶ä»çº¿ç¨ææï¼å°±ä¼é»å¡çå¾
ã
>
> å¨é»å¡çå¾
çè¿ç¨ä¸ï¼å¦æå
¶ä»çº¿ç¨ä¸æå½åçº¿ç¨ `interrupt()` ï¼å°±ä¼æåº `InterruptedException` å¼å¸¸ï¼å¯ä»¥æè·è¯¥å¼å¸¸ï¼åä¸äºå¤çæä½ã
>
> ä¸ºäºæ´å¥½çè§£è¿ä¸ªæ¹æ³ï¼åç¨ Stack Overflow ä¸çä¸ä¸ªæ¡ä¾ï¼å¯ä»¥æ´å¥½å°çè§£ `lockInterruptibly()` å¯ä»¥ååºä¸æï¼
>
> ```JAVA
> public class MyRentrantlock {
> Thread t = new Thread() {
> @Override
> public void run() {
> ReentrantLock r = new ReentrantLock();
> // 1.1ãç¬¬ä¸æ¬¡å°è¯è·åéï¼å¯ä»¥è·åæå
> r.lock();
>
> // 1.2ãæ¤æ¶éçéå
¥æ¬¡æ°ä¸º 1
> System.out.println("lock() : lock count :" + r.getHoldCount());
>
> // 2ã䏿å½å线ç¨ï¼éè¿ Thread.currentThread().isInterrupted() å¯ä»¥çå°å½å线ç¨çä¸æç¶æä¸º true
> interrupt();
> System.out.println("Current thread is intrupted");
>
> // 3.1ãå°è¯è·åéï¼å¯ä»¥æåè·å
> r.tryLock();
> // 3.2ãæ¤æ¶éçéå
¥æ¬¡æ°ä¸º 2
> System.out.println("tryLock() on intrupted thread lock count :" + r.getHoldCount());
> try {
> // 4ãæå°çº¿ç¨çä¸æç¶æä¸º trueï¼é£ä¹è°ç¨ lockInterruptibly() æ¹æ³å°±ä¼æåº InterruptedException å¼å¸¸
> System.out.println("Current Thread isInterrupted:" + Thread.currentThread().isInterrupted());
> r.lockInterruptibly();
> System.out.println("lockInterruptibly() --NOt executable statement" + r.getHoldCount());
> } catch (InterruptedException e) {
> r.lock();
> System.out.println("Error");
> } finally {
> r.unlock();
> }
>
> // 5ãæå°éçéå
¥æ¬¡æ°ï¼å¯ä»¥åç° lockInterruptibly() æ¹æ³å¹¶æ²¡ææåè·åå°é
> System.out.println("lockInterruptibly() not able to Acqurie lock: lock count :" + r.getHoldCount());
>
> r.unlock();
> System.out.println("lock count :" + r.getHoldCount());
> r.unlock();
> System.out.println("lock count :" + r.getHoldCount());
> }
> };
> public static void main(String str[]) {
> MyRentrantlock m = new MyRentrantlock();
> m.t.start();
> }
> }
> ```
>
> è¾åºï¼
>
> ```BASH
> lock() : lock count :1
> Current thread is intrupted
> tryLock() on intrupted thread lock count :2
> Current Thread isInterrupted:true
> Error
> lockInterruptibly() not able to Acqurie lock: lock count :2
> lock count :1
> lock count :0
> ```
å
³äº **æ¯æè¶
æ¶** çè¡¥å
ï¼
> **为ä»ä¹éè¦ `tryLock(timeout)` è¿ä¸ªåè½å¢ï¼**
>
> `tryLock(timeout)` æ¹æ³å°è¯å¨æå®çè¶
æ¶æ¶é´å
è·åéã妿æåè·åéï¼åè¿å `true`ï¼å¦æå¨éå¯ç¨ä¹åè¶
æ¶ï¼åè¿å `false`ãæ¤åè½å¨ä»¥ä¸å ç§åºæ¯ä¸é常æç¨ï¼
>
> - **鲿¢æ»éï¼** å¨å¤æçéåºæ¯ä¸ï¼`tryLock(timeout)` å¯ä»¥éè¿å
许线ç¨å¨åççæ¶é´å
æ¾å¼å¹¶éè¯æ¥å¸®å©é²æ¢æ»éã
> - **æé«ååºé度ï¼** 鲿¢çº¿ç¨æ éæé»å¡ã
> - **å¤çæ¶é´ææçæä½ï¼** 对äºå
·æä¸¥æ ¼æ¶é´éå¶çæä½ï¼`tryLock(timeout)` å
许线ç¨å¨æ æ³åæ¶è·åéæ¶ç»§ç»æ§è¡æ¿ä»£æä½ã
### å¯ä¸æéåä¸å¯ä¸æéæä»ä¹åºå«ï¼
- **å¯ä¸æé**ï¼è·åéçè¿ç¨ä¸å¯ä»¥è¢«ä¸æï¼ä¸éè¦ä¸ç´çå°è·åéä¹å æè½è¿è¡å
¶ä»é»è¾å¤çã`ReentrantLock` å°±å±äºæ¯å¯ä¸æéã
- **ä¸å¯ä¸æé**ï¼ä¸æ¦çº¿ç¨ç³è¯·äºéï¼å°±åªè½çå°æ¿å°é以åæè½è¿è¡å
¶ä»çé»è¾å¤çã `synchronized` å°±å±äºæ¯ä¸å¯ä¸æéã
## ReentrantReadWriteLock
`ReentrantReadWriteLock` å¨å®é
项ç®ä¸ä½¿ç¨çå¹¶ä¸å¤ï¼é¢è¯ä¸ä¹é®çæ¯è¾å°ï¼ç®åäºè§£å³å¯ãJDK 1.8 å¼å
¥äºæ§è½æ´å¥½ç读åé `StampedLock` ã
### ReentrantReadWriteLock æ¯ä»ä¹ï¼
`ReentrantReadWriteLock` å®ç°äº `ReadWriteLock` ï¼æ¯ä¸ä¸ªå¯éå
¥ç读åéï¼æ¢å¯ä»¥ä¿è¯å¤ä¸ªçº¿ç¨åæ¶è¯»çæçï¼åæ¶åå¯ä»¥ä¿è¯æåå
¥æä½æ¶ç线ç¨å®å
¨ã
```java
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable{
}
public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
}
```
- ä¸è¬éè¿è¡å¹¶åæ§å¶çè§åï¼è¯»è¯»äºæ¥ã读åäºæ¥ãååäºæ¥ã
- 读åéè¿è¡å¹¶åæ§å¶çè§åï¼è¯»è¯»ä¸äºæ¥ã读åäºæ¥ãååäºæ¥ï¼åªæè¯»è¯»ä¸äºæ¥ï¼ã
`ReentrantReadWriteLock` å
¶å®æ¯ä¸¤æéï¼ä¸ææ¯ `WriteLock` (åé)ï¼ä¸ææ¯ `ReadLock`ï¼è¯»éï¼ ãè¯»éæ¯å
±äº«éï¼å鿝ç¬å éã读éå¯ä»¥è¢«åæ¶è¯»ï¼å¯ä»¥åæ¶è¢«å¤ä¸ªçº¿ç¨ææï¼èåéæå¤åªè½åæ¶è¢«ä¸ä¸ªçº¿ç¨ææã
å `ReentrantLock` 䏿 ·ï¼`ReentrantReadWriteLock` åºå±ä¹æ¯åºäº AQS å®ç°çã

`ReentrantReadWriteLock` 乿¯æå
¬å¹³éåéå
¬å¹³éï¼é»è®¤ä½¿ç¨éå
¬å¹³éï¼å¯ä»¥éè¿æé 卿¥æ¾å¼å°æå®ã
```java
// ä¼ å
¥ä¸ä¸ª boolean å¼ï¼true æ¶ä¸ºå
¬å¹³éï¼false æ¶ä¸ºéå
¬å¹³é
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
```
### ReentrantReadWriteLock éåä»ä¹åºæ¯ï¼
ç±äº `ReentrantReadWriteLock` æ¢å¯ä»¥ä¿è¯å¤ä¸ªçº¿ç¨åæ¶è¯»çæçï¼åæ¶åå¯ä»¥ä¿è¯æåå
¥æä½æ¶ç线ç¨å®å
¨ãå æ¤ï¼å¨è¯»å¤åå°çæ
åµä¸ï¼ä½¿ç¨ `ReentrantReadWriteLock` è½å¤ææ¾æåç³»ç»æ§è½ã
### å
±äº«éåç¬å éæä»ä¹åºå«ï¼
- **å
±äº«é**ï¼ä¸æéå¯ä»¥è¢«å¤ä¸ªçº¿ç¨åæ¶è·å¾ã
- **ç¬å é**ï¼ä¸æéåªè½è¢«ä¸ä¸ªçº¿ç¨è·å¾ã
### çº¿ç¨ææè¯»éè¿è½è·ååéåï¼
- å¨çº¿ç¨ææè¯»éçæ
åµä¸ï¼è¯¥çº¿ç¨ä¸è½åå¾åé(å 为è·ååéçæ¶åï¼å¦æåç°å½åç读é被å ç¨ï¼å°±é©¬ä¸è·å失败ï¼ä¸ç®¡è¯»éæ¯ä¸æ¯è¢«å½åçº¿ç¨ææ)ã
- å¨çº¿ç¨ææåéçæ
åµä¸ï¼è¯¥çº¿ç¨å¯ä»¥ç»§ç»è·å读éï¼è·åè¯»éæ¶å¦æåç°åé被å ç¨ï¼åªæåéæ²¡æè¢«å½å线ç¨å ç¨çæ
嵿ä¼è·å失败ï¼ã
读åéçæºç åæï¼æ¨èé
读 [èè Java çå æ JVM 级é - é¿éå·´å·´ä¸é´ä»¶](https://mp.weixin.qq.com/s/h3VIUyH9L0v14MrQJiiDbw) è¿ç¯æç« ï¼åçå¾ä¸éã
### 读é为ä»ä¹ä¸è½å级为åéï¼
åéå¯ä»¥é级为读éï¼ä½æ¯è¯»éå´ä¸è½å级为åéãè¿æ¯å 为读éå级为åéä¼å¼èµ·çº¿ç¨çäºå¤ºï¼æ¯ç«åéå±äºæ¯ç¬å éï¼è¿æ ·çè¯ï¼ä¼å½±åæ§è½ã
å¦å¤ï¼è¿å¯è½ä¼ææ»éé®é¢åçã举个ä¾åï¼å设两个线ç¨ç读é齿³å级åéï¼åéè¦å¯¹æ¹é½éæ¾èªå·±éï¼èåæ¹é½ä¸éæ¾ï¼å°±ä¼äº§çæ»éã
## ThreadLocal
### ThreadLocal æä»ä¹ç¨ï¼
é常æ
åµä¸ï¼æä»¬å建çåéå¯ä»¥è¢«ä»»ä½ä¸ä¸ªçº¿ç¨è®¿é®åä¿®æ¹ãè¿å¨å¤çº¿ç¨ç¯å¢ä¸å¯è½å¯¼è´æ°æ®ç«äºå线ç¨å®å
¨é®é¢ãé£ä¹ï¼**妿æ³è®©æ¯ä¸ªçº¿ç¨é½æèªå·±çä¸å±æ¬å°åéï¼è¯¥å¦ä½å®ç°å¢ï¼**
JDK 䏿ä¾ç `ThreadLocal` ç±»æ£æ¯ä¸ºäºè§£å³è¿ä¸ªé®é¢ã**`ThreadLocal` ç±»å
许æ¯ä¸ªçº¿ç¨ç»å®èªå·±çå¼**ï¼å¯ä»¥å°å
¶å½¢è±¡å°æ¯å»ä¸ºä¸ä¸ªâåæ¾æ°æ®ççåâãæ¯ä¸ªçº¿ç¨é½æèªå·±ç¬ç«ççåï¼ç¨äºåå¨ç§ææ°æ®ï¼ç¡®ä¿ä¸å线ç¨ä¹é´çæ°æ®äºä¸å¹²æ°ã
å½ä½ å建ä¸ä¸ª `ThreadLocal` åéæ¶ï¼æ¯ä¸ªè®¿é®è¯¥åéç线ç¨é½ä¼æ¥æä¸ä¸ªç¬ç«ç坿¬ãè¿ä¹æ¯ `ThreadLocal` åç§°çç±æ¥ã线ç¨å¯ä»¥éè¿ `get()` æ¹æ³è·åèªå·±çº¿ç¨çæ¬å°å¯æ¬ï¼æéè¿ `set()` æ¹æ³ä¿®æ¹è¯¥å¯æ¬çå¼ï¼ä»èé¿å
äºçº¿ç¨å®å
¨é®é¢ã
举个ç®åçä¾åï¼å设æä¸¤ä¸ªäººå»å®å±æ¶éå®ç©ã妿ä»ä»¬å
±ç¨ä¸ä¸ªè¢åï¼å¿
ç¶ä¼äº§çäºæ§ï¼ä½å¦ææ¯ä¸ªäººé½æä¸ä¸ªç¬ç«çè¢åï¼å°±ä¸ä¼æè¿ä¸ªé®é¢ã妿å°è¿ä¸¤ä¸ªäººæ¯ä½çº¿ç¨ï¼é£ä¹ `ThreadLocal` å°±æ¯ç¨æ¥é¿å
è¿ä¸¤ä¸ªçº¿ç¨ç«äºåä¸ä¸ªèµæºçæ¹æ³ã
```java
public class ThreadLocalExample {
private static ThreadLocal threadLocal = ThreadLocal.withInitial(() -> 0);
public static void main(String[] args) {
Runnable task = () -> {
int value = threadLocal.get();
value += 1;
threadLocal.set(value);
System.out.println(Thread.currentThread().getName() + " Value: " + threadLocal.get());
};
Thread thread1 = new Thread(task, "Thread-1");
Thread thread2 = new Thread(task, "Thread-2");
thread1.start(); // è¾åº: Thread-1 Value: 1
thread2.start(); // è¾åº: Thread-2 Value: 1
}
}
```
### âï¸ThreadLocal åçäºè§£åï¼
ä» `Thread`ç±»æºä»£ç å
¥æã
```java
public class Thread implements Runnable {
//......
//䏿¤çº¿ç¨æå
³çThreadLocalå¼ãç±ThreadLocal类维æ¤
ThreadLocal.ThreadLocalMap threadLocals = null;
//䏿¤çº¿ç¨æå
³çInheritableThreadLocalå¼ãç±InheritableThreadLocal类维æ¤
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//......
}
```
ä»ä¸é¢`Thread`ç±» æºä»£ç å¯ä»¥çåº`Thread` ç±»ä¸æä¸ä¸ª `threadLocals` å ä¸ä¸ª `inheritableThreadLocals` åéï¼å®ä»¬é½æ¯ `ThreadLocalMap` ç±»åçåé,æä»¬å¯ä»¥æ `ThreadLocalMap` ç解为`ThreadLocal` ç±»å®ç°çå®å¶åç `HashMap`ãé»è®¤æ
åµä¸è¿ä¸¤ä¸ªåé齿¯ nullï¼åªæå½å线ç¨è°ç¨ `ThreadLocal` ç±»ç `set`æ`get`æ¹æ³æ¶æå建å®ä»¬ï¼å®é
ä¸è°ç¨è¿ä¸¤ä¸ªæ¹æ³çæ¶åï¼æä»¬è°ç¨çæ¯`ThreadLocalMap`类对åºç `get()`ã`set()`æ¹æ³ã
`ThreadLocal`ç±»ç`set()`æ¹æ³
```java
public void set(T value) {
//è·åå½å请æ±ç线ç¨
Thread t = Thread.currentThread();
//ååº Thread ç±»å
é¨ç threadLocals åé(åå¸è¡¨ç»æ)
ThreadLocalMap map = getMap(t);
if (map != null)
// å°éè¦åå¨ç弿¾å
¥å°è¿ä¸ªåå¸è¡¨ä¸
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
```
éè¿ä¸é¢è¿äºå
å®¹ï¼æä»¬è¶³ä»¥éè¿çæµå¾åºç»è®ºï¼**æç»çå鿝æ¾å¨äºå½å线ç¨ç `ThreadLocalMap` ä¸ï¼å¹¶ä¸æ¯åå¨ `ThreadLocal` ä¸ï¼`ThreadLocal` å¯ä»¥çè§£ä¸ºåªæ¯`ThreadLocalMap`çå°è£
ï¼ä¼ éäºåéå¼ã** `ThrealLocal` ç±»ä¸å¯ä»¥éè¿`Thread.currentThread()`è·åå°å½å线ç¨å¯¹è±¡åï¼ç´æ¥éè¿`getMap(Thread t)`å¯ä»¥è®¿é®å°è¯¥çº¿ç¨ç`ThreadLocalMap`对象ã
**æ¯ä¸ª`Thread`ä¸é½å
·å¤ä¸ä¸ª`ThreadLocalMap`ï¼è`ThreadLocalMap`å¯ä»¥åå¨ä»¥`ThreadLocal`为 key ï¼Object 对象为 value çé®å¼å¯¹ã**
```java
ThreadLocalMap(ThreadLocal> firstKey, Object firstValue) {
//......
}
```
æ¯å¦æä»¬å¨åä¸ä¸ªçº¿ç¨ä¸å£°æäºä¸¤ä¸ª `ThreadLocal` 对象çè¯ï¼ `Thread`å
é¨é½æ¯ä½¿ç¨ä»
æçé£ä¸ª`ThreadLocalMap` åæ¾æ°æ®çï¼`ThreadLocalMap`ç key å°±æ¯ `ThreadLocal`对象ï¼value å°±æ¯ `ThreadLocal` 对象è°ç¨`set`æ¹æ³è®¾ç½®çå¼ã
`ThreadLocal` æ°æ®ç»æå¦ä¸å¾æç¤ºï¼

`ThreadLocalMap`æ¯`ThreadLocal`çéæå
é¨ç±»ã

### âï¸ThreadLocal å
åæ³é²é®é¢æ¯æä¹å¯¼è´çï¼
`ThreadLocal` å
åæ³æ¼çæ ¹æ¬åå å¨äºå
¶å
é¨å®ç°æºå¶ã
éè¿ä¸é¢çå
容æä»¬å·²ç»ç¥éï¼æ¯ä¸ªçº¿ç¨ç»´æ¤ä¸ä¸ªå为 `ThreadLocalMap` ç mapã å½ä½ ä½¿ç¨ `ThreadLocal` åå¨å¼æ¶ï¼å®é
䏿¯å°å¼åå¨å¨å½å线ç¨ç `ThreadLocalMap` ä¸ï¼å
¶ä¸ `ThreadLocal` å®ä¾æ¬èº«ä½ä¸º keyï¼èä½ è¦åå¨çå¼ä½ä¸º valueã
`ThreadLocal` ç `set()` æ¹æ³æºç å¦ä¸ï¼
```java
public void set(T value) {
Thread t = Thread.currentThread(); // è·åå½å线ç¨
ThreadLocalMap map = getMap(t); // è·åå½å线ç¨ç ThreadLocalMap
if (map != null) {
map.set(this, value); // 设置å¼
} else {
createMap(t, value); // å建æ°ç ThreadLocalMap
}
}
```
`ThreadLocalMap` ç `set()` å `createMap()` æ¹æ³ä¸ï¼å¹¶æ²¡æç´æ¥åå¨ `ThreadLocal` 对象æ¬èº«ï¼èæ¯ä½¿ç¨ `ThreadLocal` çåå¸å¼è®¡ç®æ°ç»ç´¢å¼ï¼æç»åå¨äºç±»å为`static class Entry extends WeakReference>`çæ°ç»ä¸ã
```java
int i = key.threadLocalHashCode & (len-1);
```
`ThreadLocalMap` ç `Entry` å®ä¹å¦ä¸ï¼
```java
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
```
`ThreadLocalMap` ç `key` å `value` å¼ç¨æºå¶ï¼
- **key æ¯å¼±å¼ç¨**ï¼`ThreadLocalMap` ä¸ç key æ¯ `ThreadLocal` çå¼±å¼ç¨ (`WeakReference>`)ã è¿æå³çï¼å¦æ `ThreadLocal` å®ä¾ä¸å被任ä½å¼ºå¼ç¨æåï¼åå¾åæ¶å¨ä¼å¨ä¸æ¬¡ GC æ¶åæ¶è¯¥å®ä¾ï¼å¯¼è´ `ThreadLocalMap` ä¸å¯¹åºç key å为 `null`ã
- **value æ¯å¼ºå¼ç¨**ï¼å³ä½¿ `key` 被 GC åæ¶ï¼`value` ä»ç¶è¢« `ThreadLocalMap.Entry` 强å¼ç¨åå¨ï¼æ æ³è¢« GC åæ¶ã
å½ `ThreadLocal` å®ä¾å¤±å»å¼ºå¼ç¨åï¼å
¶å¯¹åºç value ä»ç¶åå¨äº `ThreadLocalMap` ä¸ï¼å 为 `Entry` 对象强å¼ç¨äºå®ãå¦æçº¿ç¨æç»åæ´»ï¼ä¾å¦çº¿ç¨æ± ä¸ç线ç¨ï¼ï¼`ThreadLocalMap` ä¹ä¼ä¸ç´åå¨ï¼å¯¼è´ key 为 `null` ç entry æ æ³è¢«åå¾åæ¶ï¼å³ä¼é æå
åæ³æ¼ã
ä¹å°±æ¯è¯´ï¼å
åæ³æ¼çåçéè¦åæ¶æ»¡è¶³ä¸¤ä¸ªæ¡ä»¶ï¼
1. `ThreadLocal` å®ä¾ä¸å被强å¼ç¨ï¼
2. çº¿ç¨æç»åæ´»ï¼å¯¼è´ `ThreadLocalMap` é¿æåå¨ã
è½ç¶ `ThreadLocalMap` å¨ `get()`, `set()` å `remove()` æä½æ¶ä¼å°è¯æ¸
ç key 为 null ç entryï¼ä½è¿ç§æ¸
çæºå¶æ¯è¢«å¨çï¼å¹¶ä¸å®å
¨å¯é ã
**å¦ä½é¿å
å
åæ³æ¼çåçï¼**
1. å¨ä½¿ç¨å® `ThreadLocal` åï¼å¡å¿
è°ç¨ `remove()` æ¹æ³ã è¿æ¯æå®å
¨åææ¨èçåæ³ã `remove()` æ¹æ³ä¼ä» `ThreadLocalMap` 䏿¾å¼å°ç§»é¤å¯¹åºç entryï¼å½»åºè§£å³å
åæ³æ¼çé£é©ã å³ä½¿å° `ThreadLocal` å®ä¹ä¸º `static final`ï¼ä¹å¼ºçå»ºè®®å¨æ¯æ¬¡ä½¿ç¨åè°ç¨ `remove()`ã
2. å¨çº¿ç¨æ± ç线ç¨å¤ç¨çåºæ¯ä¸ï¼ä½¿ç¨ `try-finally` åå¯ä»¥ç¡®ä¿å³ä½¿åçå¼å¸¸ï¼`remove()` æ¹æ³ä¹ä¸å®ä¼è¢«æ§è¡ã
### âï¸å¦ä½è·¨çº¿ç¨ä¼ é ThreadLocal çå¼ï¼
ç±äº `ThreadLocal` çåéå¼åæ¾å¨ `Thread` éï¼èç¶å线ç¨å±äºä¸åç `Thread` çãå æ¤å¨å¼æ¥åºæ¯ä¸ï¼ç¶å线ç¨ç `ThreadLocal` 弿 æ³è¿è¡ä¼ éã
妿æ³è¦å¨å¼æ¥åºæ¯ä¸ä¼ é `ThreadLocal` å¼ï¼æä¸¤ç§è§£å³æ¹æ¡ï¼
- `InheritableThreadLocal` ï¼`InheritableThreadLocal` æ¯ JDK1.2 æä¾çå·¥å
·ï¼ç»§æ¿èª `ThreadLocal` ãä½¿ç¨ `InheritableThreadLocal` æ¶ï¼ä¼å¨å建åçº¿ç¨æ¶ï¼ä»¤å线ç¨ç»§æ¿ç¶çº¿ç¨ä¸ç `ThreadLocal` å¼ï¼ä½æ¯æ æ³æ¯æçº¿ç¨æ± åºæ¯ä¸ç `ThreadLocal` å¼ä¼ éã
- `TransmittableThreadLocal` ï¼ `TransmittableThreadLocal` ï¼ç®ç§° TTLï¼ æ¯é¿é巴巴弿ºçå·¥å
·ç±»ï¼ç»§æ¿å¹¶å 强äº`InheritableThreadLocal`ç±»ï¼å¯ä»¥å¨çº¿ç¨æ± çåºæ¯ä¸æ¯æ `ThreadLocal` å¼ä¼ éã项ç®å°åï¼ã
#### InheritableThreadLocal åç
`InheritableThreadLocal` å®ç°äºåå»ºå¼æ¥çº¿ç¨æ¶ï¼ç»§æ¿ç¶çº¿ç¨ `ThreadLocal` å¼çåè½ãè¯¥ç±»æ¯ JDK å¢éæä¾çï¼éè¿æ¹é JDK æºç å
ä¸ç `Thread` ç±»æ¥å®ç°åå»ºçº¿ç¨æ¶ï¼`ThreadLocal` å¼çä¼ éã
**`InheritableThreadLocal` çå¼åå¨å¨åªéï¼**
å¨ `Thread` ç±»ä¸æ·»å äºä¸ä¸ªæ°ç `ThreadLocalMap` ï¼å½å为 `inheritableThreadLocals` ï¼è¯¥åéç¨äºåå¨éè¦è·¨çº¿ç¨ä¼ éç `ThreadLocal` å¼ãå¦ä¸ï¼
```JAVA
class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}
```
**å¦ä½å®æ `ThreadLocal` å¼çä¼ éï¼**
éè¿æ¹é `Thread` ç±»çæé æ¹æ³æ¥å®ç°ï¼å¨å建 `Thread` çº¿ç¨æ¶ï¼æ¿å°ç¶çº¿ç¨ç `inheritableThreadLocals` åéèµå¼ç»å线ç¨å³å¯ãç¸å
³ä»£ç å¦ä¸ï¼
```JAVA
// Thread çæé æ¹æ³ä¼è°ç¨ init() æ¹æ³
private void init(/* ... */) {
// 1ãè·åç¶çº¿ç¨
Thread parent = currentThread();
// 2ãå°ç¶çº¿ç¨ç inheritableThreadLocals èµå¼ç»å线ç¨
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}
```
#### TransmittableThreadLocal åç
JDK é»è®¤æ²¡ææ¯æçº¿ç¨æ± åºæ¯ä¸ `ThreadLocal` å¼ä¼ éçåè½ï¼å æ¤é¿é巴巴弿ºäºä¸å¥å·¥å
· `TransmittableThreadLocal` æ¥å®ç°è¯¥åè½ã
é¿éå·´å·´æ æ³æ¹å¨ JDK çæºç ï¼å æ¤ä»å
é¨éè¿ **è£
饰卿¨¡å¼** å¨åæçåè½ä¸åå¢å¼ºï¼ä»¥æ¤æ¥å®ç°çº¿ç¨æ± åºæ¯ä¸ç `ThreadLocal` å¼ä¼ éã
TTL æ¹é çå°æ¹æä¸¤å¤ï¼
- å®ç°èªå®ä¹ç `Thread` ï¼å¨ `run()` æ¹æ³å
é¨å `ThreadLocal` åéçèµå¼æä½ã
- åºäº **çº¿ç¨æ± ** è¿è¡è£
饰ï¼å¨ `execute()` æ¹æ³ä¸ï¼ä¸æäº¤ JDK å
é¨ç `Thread` ï¼èæ¯æäº¤èªå®ä¹ç `Thread` ã
妿æ³è¦æ¥çç¸å
³æºç ï¼å¯ä»¥å¼å
¥ Maven ä¾èµè¿è¡ä¸è½½ã
```XML
com.alibaba
transmittable-thread-local
2.12.0
```
#### åºç¨åºæ¯
1. **åæµæµéæ è®°**ï¼ å¨åæµåºæ¯ä¸ï¼ä½¿ç¨ `ThreadLocal` åå¨åæµæ è®°ï¼ç¨äºåºååæµæµéåç宿µéã妿æ 记丢失ï¼å¯è½å¯¼è´åæµæµé被é误å°å½æçº¿ä¸æµéå¤çã
2. **ä¸ä¸æä¼ é**ï¼å¨åå¸å¼ç³»ç»ä¸ï¼ä¼ éé¾è·¯è¿½è¸ªä¿¡æ¯ï¼å¦ Trace IDï¼æç¨æ·ä¸ä¸æä¿¡æ¯ã
## çº¿ç¨æ±
### ä»ä¹æ¯çº¿ç¨æ± ?
顾åæä¹ï¼çº¿ç¨æ± å°±æ¯ç®¡çä¸ç³»å线ç¨çèµæºæ± ã彿任å¡è¦å¤çæ¶ï¼ç´æ¥ä»çº¿ç¨æ± ä¸è·åçº¿ç¨æ¥å¤çï¼å¤çå®ä¹å线ç¨å¹¶ä¸ä¼ç«å³è¢«éæ¯ï¼èæ¯çå¾
ä¸ä¸ä¸ªä»»å¡ã
### âï¸ä¸ºä»ä¹è¦ç¨çº¿ç¨æ± ï¼
æ± åææ¯æ³å¿
大家已ç»å±¡è§ä¸é²äºï¼çº¿ç¨æ± ãæ°æ®åºè¿æ¥æ± ãHTTP è¿æ¥æ± çç齿¯å¯¹è¿ä¸ªææ³çåºç¨ãæ± åææ¯çææ³ä¸»è¦æ¯ä¸ºäºåå°æ¯æ¬¡è·åèµæºçæ¶èï¼æé«å¯¹èµæºçå©ç¨çã
çº¿ç¨æ± æä¾äºä¸ç§éå¶å管çèµæºï¼å
æ¬æ§è¡ä¸ä¸ªä»»å¡ï¼çæ¹å¼ã æ¯ä¸ªçº¿ç¨æ± è¿ç»´æ¤ä¸äºåºæ¬ç»è®¡ä¿¡æ¯ï¼ä¾å¦å·²å®æä»»å¡çæ°éã使ç¨çº¿ç¨æ± 主è¦å¸¦æ¥ä»¥ä¸å 个好å¤ï¼
1. **éä½èµæºæ¶è**ï¼çº¿ç¨æ± éççº¿ç¨æ¯å¯ä»¥éå¤å©ç¨çã䏿¦çº¿ç¨å®æäºæä¸ªä»»å¡ï¼å®ä¸ä¼ç«å³éæ¯ï¼èæ¯åå°æ± åéçå¾
ä¸ä¸ä¸ªä»»å¡ãè¿å°±é¿å
äºé¢ç¹å建åéæ¯çº¿ç¨å¸¦æ¥çå¼éã
2. **æé«ååºé度**ï¼å ä¸ºçº¿ç¨æ± éé常ä¼ç»´æ¤ä¸å®æ°éçæ ¸å¿çº¿ç¨ï¼æè
说â常驻工人âï¼ï¼ä»»å¡æ¥äºä¹åï¼å¯ä»¥ç´æ¥äº¤ç»è¿äºå·²ç»åå¨çã空é²ç线ç¨å»æ§è¡ï¼çå»äºå建线ç¨çæ¶é´ï¼ä»»å¡è½å¤æ´å¿«å°å¾å°å¤çã
3. **æé«çº¿ç¨çå¯ç®¡çæ§**ï¼çº¿ç¨æ± å
许æä»¬ç»ä¸ç®¡çæ± ä¸ç线ç¨ãæä»¬å¯ä»¥é
ç½®çº¿ç¨æ± ç大å°ï¼æ ¸å¿çº¿ç¨æ°ãæå¤§çº¿ç¨æ°ï¼ãä»»å¡éåçç±»åå大å°ãæç»çç¥çãè¿æ ·å°±è½æ§å¶å¹¶å线ç¨çæ»éï¼é²æ¢èµæºèå°½ï¼ä¿è¯ç³»ç»çç¨³å®æ§ãåæ¶ï¼çº¿ç¨æ± é叏乿ä¾äºçæ§æ¥å£ï¼æ¹ä¾¿æä»¬äºè§£çº¿ç¨æ± çè¿è¡ç¶æï¼æ¯å¦æå¤å°æ´»è·çº¿ç¨ãå¤å°ä»»å¡å¨æéçï¼ï¼ä¾¿äºè°ä¼ã
### å¦ä½åå»ºçº¿ç¨æ± ï¼
å¨ Java ä¸ï¼åå»ºçº¿ç¨æ± ä¸»è¦æä¸¤ç§æ¹å¼ï¼
**æ¹å¼ä¸ï¼éè¿ `ThreadPoolExecutor` æé 彿°ç´æ¥å建 (æ¨è)**

è¿æ¯ææ¨èçæ¹å¼ï¼å 为å®å
许å¼åè
æç¡®æå®çº¿ç¨æ± çæ ¸å¿åæ°ï¼å¯¹çº¿ç¨æ± çè¿è¡è¡ä¸ºææ´ç²¾ç»çæ§å¶ï¼ä»èé¿å
èµæºèå°½çé£é©ã
**æ¹å¼äºï¼éè¿ `Executors` å·¥å
·ç±»å建 (䏿¨èç¨äºç产ç¯å¢)**
`Executors`å·¥å
·ç±»æä¾çåå»ºçº¿ç¨æ± çæ¹æ³å¦ä¸å¾æç¤ºï¼

å¯ä»¥çåºï¼éè¿`Executors`å·¥å
·ç±»å¯ä»¥å建å¤ç§ç±»åççº¿ç¨æ± ï¼å
æ¬ï¼
- `FixedThreadPool`ï¼åºå®çº¿ç¨æ°éççº¿ç¨æ± ãè¯¥çº¿ç¨æ± ä¸ççº¿ç¨æ°éå§ç»ä¸åã彿ä¸ä¸ªæ°çä»»å¡æäº¤æ¶ï¼çº¿ç¨æ± ä¸è¥æç©ºé²çº¿ç¨ï¼åç«å³æ§è¡ãè¥æ²¡æï¼åæ°çä»»å¡ä¼è¢«æåå¨ä¸ä¸ªä»»å¡éåä¸ï¼å¾
æçº¿ç¨ç©ºé²æ¶ï¼ä¾¿å¤çå¨ä»»å¡éåä¸çä»»å¡ã
- `SingleThreadExecutor`ï¼ åªæä¸ä¸ªçº¿ç¨ççº¿ç¨æ± ãè¥å¤ä½ä¸ä¸ªä»»å¡è¢«æäº¤å°è¯¥çº¿ç¨æ± ï¼ä»»å¡ä¼è¢«ä¿åå¨ä¸ä¸ªä»»å¡éåä¸ï¼å¾
线ç¨ç©ºé²ï¼æå
å
¥å
åºçé¡ºåºæ§è¡éåä¸çä»»å¡ã
- `CachedThreadPool`ï¼ å¯æ ¹æ®å®é
æ
åµè°æ´çº¿ç¨æ°éççº¿ç¨æ± ãçº¿ç¨æ± ççº¿ç¨æ°éä¸ç¡®å®ï¼ä½è¥æç©ºé²çº¿ç¨å¯ä»¥å¤ç¨ï¼åä¼ä¼å
使ç¨å¯å¤ç¨ç线ç¨ãè¥ææçº¿ç¨åå¨å·¥ä½ï¼åææ°çä»»å¡æäº¤ï¼åä¼å建æ°ç线ç¨å¤çä»»å¡ãææçº¿ç¨å¨å½å任塿§è¡å®æ¯åï¼å°è¿åçº¿ç¨æ± è¿è¡å¤ç¨ã
- `ScheduledThreadPool`ï¼ç»å®çå»¶è¿åè¿è¡ä»»å¡æè
宿æ§è¡ä»»å¡ççº¿ç¨æ± ã
### âï¸ä¸ºä»ä¹ä¸æ¨è使ç¨å
ç½®çº¿ç¨æ± ï¼
å¨ãé¿éå·´å·´ Java å¼åæåãâå¹¶åå¤çâè¿ä¸ç« èï¼æç¡®æåºçº¿ç¨èµæºå¿
é¡»éè¿çº¿ç¨æ± æä¾ï¼ä¸å
许å¨åºç¨ä¸èªè¡æ¾å¼å建线ç¨ã
**为ä»ä¹å¢ï¼**
> 使ç¨çº¿ç¨æ± ç好夿¯åå°å¨å建åéæ¯çº¿ç¨ä¸ææ¶èçæ¶é´ä»¥åç³»ç»èµæºå¼éï¼è§£å³èµæºä¸è¶³çé®é¢ã妿ä¸ä½¿ç¨çº¿ç¨æ± ï¼æå¯è½ä¼é æç³»ç»å建大éå类线ç¨èå¯¼è´æ¶èå®å
åæè
âè¿åº¦åæ¢âçé®é¢ã
å¦å¤ï¼ãé¿éå·´å·´ Java å¼åæåãä¸å¼ºå¶çº¿ç¨æ± ä¸å
è®¸ä½¿ç¨ `Executors` å»å建ï¼èæ¯éè¿ `ThreadPoolExecutor` æé 彿°çæ¹å¼ï¼è¿æ ·çå¤çæ¹å¼è®©åçå妿´å æç¡®çº¿ç¨æ± çè¿è¡è§åï¼è§é¿èµæºèå°½çé£é©
`Executors` è¿åçº¿ç¨æ± 对象çå¼ç«¯å¦ä¸(åæä¼è¯¦ç»ä»ç»å°)ï¼
- `FixedThreadPool` å `SingleThreadExecutor`:使ç¨çæ¯é»å¡éå `LinkedBlockingQueue`ï¼ä»»å¡éåæå¤§é¿åº¦ä¸º `Integer.MAX_VALUE`ï¼å¯ä»¥ç使¯æ ççï¼å¯è½å 积大éç请æ±ï¼ä»èå¯¼è´ OOMã
- `CachedThreadPool`:使ç¨çæ¯åæ¥éå `SynchronousQueue`, å
许å建ççº¿ç¨æ°é为 `Integer.MAX_VALUE` ï¼å¦æä»»å¡æ°éè¿å¤ä¸æ§è¡éåº¦è¾æ
¢ï¼å¯è½ä¼å建大éç线ç¨ï¼ä»èå¯¼è´ OOMã
- `ScheduledThreadPool` å `SingleThreadScheduledExecutor`:使ç¨çæ ççå»¶è¿é»å¡éå`DelayedWorkQueue`ï¼ä»»å¡éåæå¤§é¿åº¦ä¸º `Integer.MAX_VALUE`,å¯è½å 积大éç请æ±ï¼ä»èå¯¼è´ OOMã
```java
public static ExecutorService newFixedThreadPool(int nThreads) {
// LinkedBlockingQueue çé»è®¤é¿åº¦ä¸º Integer.MAX_VALUEï¼å¯ä»¥ç使¯æ çç
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
}
public static ExecutorService newSingleThreadExecutor() {
// LinkedBlockingQueue çé»è®¤é¿åº¦ä¸º Integer.MAX_VALUEï¼å¯ä»¥ç使¯æ çç
return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue()));
}
// 忥éå SynchronousQueueï¼æ²¡æå®¹éï¼æå¤§çº¿ç¨æ°æ¯ Integer.MAX_VALUE`
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue());
}
// DelayedWorkQueueï¼å»¶è¿é»å¡éåï¼
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
```
### âï¸çº¿ç¨æ± 常è§åæ°æåªäºï¼å¦ä½è§£éï¼
```java
/**
* ç¨ç»å®çåå§åæ°å建ä¸ä¸ªæ°çThreadPoolExecutorã
*/
public ThreadPoolExecutor(int corePoolSize,//çº¿ç¨æ± çæ ¸å¿çº¿ç¨æ°é
int maximumPoolSize,//çº¿ç¨æ± çæå¤§çº¿ç¨æ°
long keepAliveTime,//å½çº¿ç¨æ°å¤§äºæ ¸å¿çº¿ç¨æ°æ¶ï¼å¤ä½ç空é²çº¿ç¨åæ´»çæé¿æ¶é´
TimeUnit unit,//æ¶é´åä½
BlockingQueue workQueue,//ä»»å¡éåï¼ç¨æ¥å¨åçå¾
æ§è¡ä»»å¡çéå
ThreadFactory threadFactory,//线ç¨å·¥åï¼ç¨æ¥å建线ç¨ï¼ä¸è¬é»è®¤å³å¯
RejectedExecutionHandler handler//æç»çç¥ï¼å½æäº¤çä»»å¡è¿å¤èä¸è½åæ¶å¤çæ¶ï¼æä»¬å¯ä»¥å®å¶çç¥æ¥å¤çä»»å¡
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
```
`ThreadPoolExecutor` 3 个æéè¦çåæ°ï¼
- `corePoolSize` : ä»»å¡éåæªè¾¾å°éåå®¹éæ¶ï¼æå¤§å¯ä»¥åæ¶è¿è¡ççº¿ç¨æ°éã
- `maximumPoolSize` : ä»»å¡éåä¸åæ¾çä»»å¡è¾¾å°éå容éçæ¶åï¼å½åå¯ä»¥åæ¶è¿è¡ççº¿ç¨æ°éå为æå¤§çº¿ç¨æ°ã
- `workQueue`: æ°ä»»å¡æ¥çæ¶åä¼å
夿å½åè¿è¡ççº¿ç¨æ°éæ¯å¦è¾¾å°æ ¸å¿çº¿ç¨æ°ï¼å¦æè¾¾å°çè¯ï¼æ°ä»»å¡å°±ä¼è¢«åæ¾å¨éåä¸ã
`ThreadPoolExecutor`å
¶ä»å¸¸è§åæ° :
- `keepAliveTime`:å½çº¿ç¨æ± ä¸ççº¿ç¨æ°éå¤§äº `corePoolSize` ï¼å³æéæ ¸å¿çº¿ç¨ï¼çº¿ç¨æ± 䏿 ¸å¿çº¿ç¨ä»¥å¤ç线ç¨ï¼æ¶ï¼è¿äºéæ ¸å¿çº¿ç¨ç©ºé²åä¸ä¼ç«å³éæ¯ï¼èæ¯ä¼çå¾
ï¼ç´å°çå¾
çæ¶é´è¶
è¿äº `keepAliveTime`æä¼è¢«åæ¶éæ¯ã
- `unit` : `keepAliveTime` åæ°çæ¶é´åä½ã
- `threadFactory` :executor å建æ°çº¿ç¨çæ¶åä¼ç¨å°ã
- `handler` :æç»çç¥ï¼åé¢ä¼åç¬è¯¦ç»ä»ç»ä¸ä¸ï¼ã
ä¸é¢è¿å¼ å¾å¯ä»¥å æ·±ä½ å¯¹çº¿ç¨æ± ä¸åä¸ªåæ°çç¸äºå
³ç³»ççè§£ï¼å¾çæ¥æºï¼ãJava æ§è½è°ä¼å®æãï¼ï¼

### çº¿ç¨æ± çæ ¸å¿çº¿ç¨ä¼è¢«åæ¶åï¼
`ThreadPoolExecutor` é»è®¤ä¸ä¼åæ¶æ ¸å¿çº¿ç¨ï¼å³ä½¿å®ä»¬å·²ç»ç©ºé²äºãè¿æ¯ä¸ºäºåå°å建线ç¨çå¼éï¼å ä¸ºæ ¸å¿çº¿ç¨é常æ¯è¦é¿æä¿ææ´»è·çã使¯ï¼å¦æçº¿ç¨æ± æ¯è¢«ç¨äºå¨ææ§ä½¿ç¨çåºæ¯ï¼ä¸é¢çä¸é«ï¼å¨æä¹é´æææ¾çç©ºé²æ¶é´ï¼ï¼å¯ä»¥èèå° `allowCoreThreadTimeOut(boolean value)` æ¹æ³çåæ°è®¾ç½®ä¸º `true`ï¼è¿æ ·å°±ä¼åæ¶ç©ºé²ï¼æ¶é´é´éç± `keepAliveTime` æå®ï¼çæ ¸å¿çº¿ç¨äºã
```java
public void allowCoreThreadTimeOut(boolean value) {
// æ ¸å¿çº¿ç¨ç keepAliveTime å¿
é¡»å¤§äº 0 æè½å¯ç¨è¶
æ¶æºå¶
if (value && keepAliveTime <= 0) {
throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
}
// 设置 allowCoreThreadTimeOut çå¼
if (value != allowCoreThreadTimeOut) {
allowCoreThreadTimeOut = value;
// 妿å¯ç¨äºè¶
æ¶æºå¶ï¼æ¸
çææç©ºé²ç线ç¨ï¼å
æ¬æ ¸å¿çº¿ç¨
if (value) {
interruptIdleWorkers();
}
}
}
```
### æ ¸å¿çº¿ç¨ç©ºé²æ¶å¤äºä»ä¹ç¶æï¼
æ ¸å¿çº¿ç¨ç©ºé²æ¶ï¼å
¶ç¶æå为以ä¸ä¸¤ç§æ
åµï¼
- **è®¾ç½®äºæ ¸å¿çº¿ç¨çåæ´»æ¶é´** ï¼æ ¸å¿çº¿ç¨å¨ç©ºé²æ¶ï¼ä¼å¤äº `WAITING` ç¶æï¼çå¾
è·åä»»å¡ã妿é»å¡çå¾
çæ¶é´è¶
è¿äºæ ¸å¿çº¿ç¨åæ´»æ¶é´ï¼å该线ç¨ä¼éåºå·¥ä½ï¼å°è¯¥çº¿ç¨ä»çº¿ç¨æ± çå·¥ä½çº¿ç¨éåä¸ç§»é¤ï¼çº¿ç¨ç¶æå为 `TERMINATED` ç¶æã
- **没æè®¾ç½®æ ¸å¿çº¿ç¨çåæ´»æ¶é´** ï¼æ ¸å¿çº¿ç¨å¨ç©ºé²æ¶ï¼ä¼ä¸ç´å¤äº `WAITING` ç¶æï¼çå¾
è·åä»»å¡ï¼æ ¸å¿çº¿ç¨ä¼ä¸ç´åæ´»å¨çº¿ç¨æ± ä¸ã
å½éå䏿å¯ç¨ä»»å¡æ¶ï¼ä¼å¤é被é»å¡ç线ç¨ï¼çº¿ç¨çç¶æä¼ç± `WAITING` ç¶æå为 `RUNNABLE` ç¶æï¼ä¹å廿§è¡å¯¹åºä»»å¡ã
æ¥ä¸æ¥éè¿ç¸å
³æºç ï¼äºè§£ä¸ä¸çº¿ç¨æ± å
鍿¯å¦ä½åçã
线ç¨å¨çº¿ç¨æ± å
é¨è¢«æ½è±¡ä¸ºäº `Worker` ï¼å½ `Worker` 被å¯å¨ä¹åï¼ä¼ä¸æå»ä»»å¡éåä¸è·åä»»å¡ã
å¨è·åä»»å¡çæ¶åï¼ä¼æ ¹æ® `timed` 弿¥å³å®ä»ä»»å¡éåï¼ `BlockingQueue` ï¼è·åä»»å¡çè¡ä¸ºã
妿ãè®¾ç½®äºæ ¸å¿çº¿ç¨çåæ´»æ¶é´ãæè
ãçº¿ç¨æ°éè¶
è¿äºæ ¸å¿çº¿ç¨æ°éãï¼åå° `timed` æ 记为 `true` ï¼è¡¨æè·å任塿¶éè¦ä½¿ç¨ `poll()` æå®è¶
æ¶æ¶é´ã
- `timed == true` ï¼ä½¿ç¨ `poll()` æ¥è·åä»»å¡ãä½¿ç¨ `poll()` æ¹æ³è·åä»»å¡è¶
æ¶çè¯ï¼åå½å线ç¨ä¼éåºæ§è¡ï¼ `TERMINATED` ï¼ï¼è¯¥çº¿ç¨ä»çº¿ç¨æ± ä¸è¢«ç§»é¤ã
- `timed == false` ï¼ä½¿ç¨ `take()` æ¥è·åä»»å¡ãä½¿ç¨ `take()` æ¹æ³è·åä»»å¡ä¼è®©å½å线ç¨ä¸ç´é»å¡çå¾
ï¼`WAITING`ï¼ã
æºç å¦ä¸ï¼
```JAVA
// ThreadPoolExecutor
private Runnable getTask() {
boolean timedOut = false;
for (;;) {
// ...
// 1ã妿ãè®¾ç½®äºæ ¸å¿çº¿ç¨çåæ´»æ¶é´ãæè
æ¯ãçº¿ç¨æ°éè¶
è¿äºæ ¸å¿çº¿ç¨æ°éãï¼å timed 为 trueã
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 2ãæ£åçº¿ç¨æ°éã
// wc > maximuimPoolSizeï¼çº¿ç¨æ± ä¸ççº¿ç¨æ°éè¶
è¿æå¤§çº¿ç¨æ°éãå
¶ä¸ wc ä¸ºçº¿ç¨æ± ä¸ççº¿ç¨æ°éã
// timed && timeOutï¼timeOut 表示è·åä»»å¡è¶
æ¶ã
// åä¸ºä¸¤ç§æ
åµï¼æ ¸å¿çº¿ç¨è®¾ç½®äºåæ´»æ¶é´ && è·åä»»å¡è¶
æ¶ï¼åæ£åçº¿ç¨æ°éï¼çº¿ç¨æ°éè¶
è¿äºæ ¸å¿çº¿ç¨æ°é && è·åä»»å¡è¶
æ¶ï¼åæ£åçº¿ç¨æ°éã
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
// 3ã妿 timed 为 trueï¼åä½¿ç¨ poll() è·åä»»å¡ï¼å¦åï¼ä½¿ç¨ take() è·åä»»å¡ã
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
// 4ãè·åä»»å¡ä¹åè¿åã
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
```
### âï¸çº¿ç¨æ± çæç»çç¥æåªäºï¼
妿å½ååæ¶è¿è¡ççº¿ç¨æ°éè¾¾å°æå¤§çº¿ç¨æ°éå¹¶ä¸éåä¹å·²ç»è¢«æ¾æ»¡äºä»»å¡æ¶ï¼`ThreadPoolExecutor` å®ä¹ä¸äºçç¥:
- `ThreadPoolExecutor.AbortPolicy`ï¼æåº `RejectedExecutionException`æ¥æç»æ°ä»»å¡çå¤çã
- `ThreadPoolExecutor.CallerRunsPolicy`ï¼è°ç¨æ§è¡è
èªå·±ç线ç¨è¿è¡ä»»å¡ï¼ä¹å°±æ¯ç´æ¥å¨è°ç¨`execute`æ¹æ³ç线ç¨ä¸è¿è¡(`run`)被æç»çä»»å¡ï¼å¦ææ§è¡ç¨åºå·²å
³éï¼åä¼ä¸¢å¼è¯¥ä»»å¡ãå æ¤è¿ç§çç¥ä¼éä½å¯¹äºæ°ä»»å¡æäº¤é度ï¼å½±åç¨åºçæ´ä½æ§è½ãå¦æä½ çåºç¨ç¨åºå¯ä»¥æ¿åæ¤å»¶è¿å¹¶ä¸ä½ è¦æ±ä»»ä½ä¸ä¸ªä»»å¡è¯·æ±é½è¦è¢«æ§è¡çè¯ï¼ä½ å¯ä»¥éæ©è¿ä¸ªçç¥ã
- `ThreadPoolExecutor.DiscardPolicy`ï¼ä¸å¤çæ°ä»»å¡ï¼ç´æ¥ä¸¢å¼æã
- `ThreadPoolExecutor.DiscardOldestPolicy`ï¼æ¤çç¥å°ä¸¢å¼ææ©çæªå¤ççä»»å¡è¯·æ±ã
举个ä¾åï¼Spring éè¿ `ThreadPoolTaskExecutor` æè
æä»¬ç´æ¥éè¿ `ThreadPoolExecutor` çæé 彿°åå»ºçº¿ç¨æ± çæ¶åï¼å½æä»¬ä¸æå® `RejectedExecutionHandler` æç»çç¥æ¥é
ç½®çº¿ç¨æ± çæ¶åï¼é»è®¤ä½¿ç¨çæ¯ `AbortPolicy`ãå¨è¿ç§æç»çç¥ä¸ï¼å¦æéåæ»¡äºï¼`ThreadPoolExecutor` å°æåº `RejectedExecutionException` å¼å¸¸æ¥æç»æ°æ¥çä»»å¡ ï¼è¿ä»£è¡¨ä½ å°ä¸¢å¤±å¯¹è¿ä¸ªä»»å¡çå¤çã妿䏿³ä¸¢å¼ä»»å¡çè¯ï¼å¯ä»¥ä½¿ç¨`CallerRunsPolicy`ã`CallerRunsPolicy` åå
¶ä»çå 个çç¥ä¸åï¼å®æ¢ä¸ä¼æå¼ä»»å¡ï¼ä¹ä¸ä¼æåºå¼å¸¸ï¼èæ¯å°ä»»å¡åéç»è°ç¨è
ï¼ä½¿ç¨è°ç¨è
ççº¿ç¨æ¥æ§è¡ä»»å¡ã
```java
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// ç´æ¥ä¸»çº¿ç¨æ§è¡ï¼è䏿¯çº¿ç¨æ± ä¸ççº¿ç¨æ§è¡
r.run();
}
}
}
```
### 妿ä¸å
许丢å¼ä»»å¡ï¼åºè¯¥éæ©åªä¸ªæç»çç¥ï¼
æ ¹æ®ä¸é¢å¯¹çº¿ç¨æ± æç»çç¥çä»ç»ï¼ç¸ä¿¡å¤§å®¶å¾å®¹æè½å¤å¾åºçæ¡æ¯ï¼`CallerRunsPolicy` ã
è¿éæä»¬åæ¥ç»å`CallerRunsPolicy` çæºç æ¥ççï¼
```java
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
//åªè¦å½åç¨åºæ²¡æå
³éï¼å°±ç¨æ§è¡executeæ¹æ³ççº¿ç¨æ§è¡è¯¥ä»»å¡
if (!e.isShutdown()) {
r.run();
}
}
}
```
仿ºç å¯ä»¥çåºï¼åªè¦å½åç¨åºä¸å
³éå°±ä¼ä½¿ç¨æ§è¡`execute`æ¹æ³ççº¿ç¨æ§è¡è¯¥ä»»å¡ã
### CallerRunsPolicy æç»çç¥æä»ä¹é£é©ï¼å¦ä½è§£å³ï¼
æä»¬ä¸é¢ä¹æå°äºï¼å¦ææ³è¦ä¿è¯ä»»ä½ä¸ä¸ªä»»å¡è¯·æ±é½è¦è¢«æ§è¡çè¯ï¼é£éæ© `CallerRunsPolicy` æç»çç¥æ´åéä¸äºã
ä¸è¿ï¼å¦æèµ°å°`CallerRunsPolicy`ç任塿¯ä¸ªéå¸¸èæ¶çä»»å¡ï¼ä¸å¤çæäº¤ä»»å¡ççº¿ç¨æ¯ä¸»çº¿ç¨ï¼å¯è½ä¼å¯¼è´ä¸»çº¿ç¨é»å¡ï¼å½±åç¨åºçæ£å¸¸è¿è¡ã
è¿éç®å举ä¸ä¸ªä¾åï¼è¯¥çº¿ç¨æ± éå®äºæå¤§çº¿ç¨æ°ä¸º 2ï¼é»å¡éå大å°ä¸º 1(è¿æå³ç第 4 个任å¡å°±ä¼èµ°å°æç»çç¥)ï¼`ThreadUtil`为 Hutool æä¾çå·¥å
·ç±»ï¼
```java
public class ThreadPoolTest {
private static final Logger log = LoggerFactory.getLogger(ThreadPoolTest.class);
public static void main(String[] args) {
// å建ä¸ä¸ªçº¿ç¨æ± ï¼æ ¸å¿çº¿ç¨æ°ä¸º1ï¼æå¤§çº¿ç¨æ°ä¸º2
// å½çº¿ç¨æ°å¤§äºæ ¸å¿çº¿ç¨æ°æ¶ï¼å¤ä½ç空é²çº¿ç¨åæ´»çæé¿æ¶é´ä¸º60ç§ï¼
// ä»»å¡éå为容é为1çArrayBlockingQueueï¼é¥±åçç¥ä¸ºCallerRunsPolicyã
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
2,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1),
new ThreadPoolExecutor.CallerRunsPolicy());
// æäº¤ç¬¬ä¸ä¸ªä»»å¡ï¼ç±æ ¸å¿çº¿ç¨æ§è¡
threadPoolExecutor.execute(() -> {
log.info("æ ¸å¿çº¿ç¨æ§è¡ç¬¬ä¸ä¸ªä»»å¡");
ThreadUtil.sleep(1, TimeUnit.MINUTES);
});
// æäº¤ç¬¬äºä¸ªä»»å¡ï¼ç±äºæ ¸å¿çº¿ç¨è¢«å ç¨ï¼ä»»å¡å°è¿å
¥éåçå¾
threadPoolExecutor.execute(() -> {
log.info("éæ ¸å¿çº¿ç¨å¤çå
¥éç第äºä¸ªä»»å¡");
ThreadUtil.sleep(1, TimeUnit.MINUTES);
});
// æäº¤ç¬¬ä¸ä¸ªä»»å¡ï¼ç±äºæ ¸å¿çº¿ç¨è¢«å ç¨ä¸éå已满ï¼åå»ºéæ ¸å¿çº¿ç¨å¤ç
threadPoolExecutor.execute(() -> {
log.info("éæ ¸å¿çº¿ç¨å¤ç第ä¸ä¸ªä»»å¡");
ThreadUtil.sleep(1, TimeUnit.MINUTES);
});
// æäº¤ç¬¬å个任å¡ï¼ç±äºæ ¸å¿çº¿ç¨åéæ ¸å¿çº¿ç¨é½è¢«å ç¨ï¼éå乿»¡äºï¼æ ¹æ®CallerRunsPolicyçç¥ï¼ä»»å¡å°ç±æäº¤ä»»å¡ç线ç¨ï¼å³ä¸»çº¿ç¨ï¼æ¥æ§è¡
threadPoolExecutor.execute(() -> {
log.info("主线ç¨å¤ç第å个任å¡");
ThreadUtil.sleep(2, TimeUnit.MINUTES);
});
// æäº¤ç¬¬äºä¸ªä»»å¡ï¼ä¸»çº¿ç¨è¢«ç¬¬å个任å¡å¡ä½ï¼è¯¥ä»»å¡å¿
é¡»çå°ä¸»çº¿ç¨æ§è¡å®æè½æäº¤
threadPoolExecutor.execute(() -> {
log.info("æ ¸å¿çº¿ç¨æ§è¡ç¬¬äºä¸ªä»»å¡");
});
// å
³éçº¿ç¨æ±
threadPoolExecutor.shutdown();
}
}
```
è¾åºï¼
```bash
18:19:48.203 INFO [pool-1-thread-1] c.j.concurrent.ThreadPoolTest - æ ¸å¿çº¿ç¨æ§è¡ç¬¬ä¸ä¸ªä»»å¡
18:19:48.203 INFO [pool-1-thread-2] c.j.concurrent.ThreadPoolTest - éæ ¸å¿çº¿ç¨å¤ç第ä¸ä¸ªä»»å¡
18:19:48.203 INFO [main] c.j.concurrent.ThreadPoolTest - 主线ç¨å¤ç第å个任å¡
18:20:48.212 INFO [pool-1-thread-2] c.j.concurrent.ThreadPoolTest - éæ ¸å¿çº¿ç¨å¤çå
¥éç第äºä¸ªä»»å¡
18:21:48.219 INFO [pool-1-thread-2] c.j.concurrent.ThreadPoolTest - æ ¸å¿çº¿ç¨æ§è¡ç¬¬äºä¸ªä»»å¡
```
ä»è¾åºç»æå¯ä»¥çåºï¼å 为`CallerRunsPolicy`è¿ä¸ªæç»çç¥ï¼å¯¼è´èæ¶çä»»å¡ç¨äºä¸»çº¿ç¨æ§è¡ï¼å¯¼è´çº¿ç¨æ± é»å¡ï¼è¿è导è´åç»ä»»å¡æ æ³åæ¶æ§è¡ï¼ä¸¥éçæ
åµä¸å¾å¯è½å¯¼è´ OOMã
æä»¬ä»é®é¢çæ¬è´¨å
¥æï¼è°ç¨è
éç¨`CallerRunsPolicy`æ¯å¸æææçä»»å¡é½è½å¤è¢«æ§è¡ï¼ææ¶æ æ³å¤ççä»»å¡å被ä¿åå¨é»å¡éå`BlockingQueue`ä¸ãè¿æ ·çè¯ï¼å¨å
åå
许çæ
åµä¸ï¼æä»¬å¯ä»¥å¢å é»å¡éå`BlockingQueue`ç大å°å¹¶è°æ´å å
å以容纳æ´å¤çä»»å¡ï¼ç¡®ä¿ä»»å¡è½å¤è¢«åç¡®æ§è¡ã
为äºå
åå©ç¨ CPUï¼æä»¬è¿å¯ä»¥è°æ´çº¿ç¨æ± ç`maximumPoolSize` ï¼æå¤§çº¿ç¨æ°ï¼åæ°ï¼è¿æ ·å¯ä»¥æé«ä»»å¡å¤çé度ï¼é¿å
ç´¯è®¡å¨ `BlockingQueue`çä»»å¡è¿å¤å¯¼è´å
åç¨å®ã

妿æå¡å¨èµæºä»¥è¾¾å°å¯å©ç¨çæéï¼è¿å°±æå³æä»¬è¦å¨è®¾è®¡çç¥ä¸æ¹åçº¿ç¨æ± çè°åº¦äºï¼æä»¬é½ç¥éï¼å¯¼è´ä¸»çº¿ç¨å¡æ»çæ¬è´¨å°±æ¯å 为æä»¬ä¸å¸æä»»ä½ä¸ä¸ªä»»å¡è¢«ä¸¢å¼ãæ¢ä¸ªæè·¯ï¼ææ²¡æåæ³æ¢è½ä¿è¯ä»»å¡ä¸è¢«ä¸¢å¼ä¸å¨æå¡å¨æä½åæ¶åæ¶å¤çå¢ï¼
è¿éæä¾çä¸ç§**任塿ä¹
å**çæè·¯ï¼è¿éæè°ç任塿ä¹
åï¼å
æ¬ä½ä¸éäº:
1. 设计ä¸å¼ ä»»å¡è¡¨å°ä»»å¡åå¨å° MySQL æ°æ®åºä¸ã
2. Redis ç¼åä»»å¡ã
3. å°ä»»å¡æäº¤å°æ¶æ¯éåä¸ã
è¿éä»¥æ¹æ¡ä¸ä¸ºä¾ï¼ç®åä»ç»ä¸ä¸å®ç°é»è¾ï¼
1. å®ç°`RejectedExecutionHandler`æ¥å£èªå®ä¹æç»çç¥ï¼èªå®ä¹æç»çç¥è´è´£å°çº¿ç¨æ± ææ¶æ æ³å¤çï¼æ¤æ¶é»å¡éå已满ï¼çä»»å¡å
¥åºï¼ä¿åå° MySQL ä¸ï¼ã注æï¼çº¿ç¨æ± ææ¶æ æ³å¤ççä»»å¡ä¼å
被æ¾å¨é»å¡éåä¸ï¼é»å¡éåæ»¡äºæä¼è§¦åæç»çç¥ã
2. ç»§æ¿`BlockingQueue`å®ç°ä¸ä¸ªæ··åå¼é»å¡éåï¼è¯¥éåå
å« JDK èªå¸¦ç`ArrayBlockingQueue`ãå¦å¤ï¼è¯¥æ··åå¼é»å¡éåéè¦ä¿®æ¹åä»»å¡å¤ççé»è¾ï¼ä¹å°±æ¯éå`take()`æ¹æ³ï¼å任塿¶ä¼å
仿°æ®åºä¸è¯»åææ©çä»»å¡ï¼æ°æ®åºä¸æ 任塿¶åä» `ArrayBlockingQueue`ä¸å»åä»»å¡ã

æ´ä¸ªå®ç°é»è¾è¿æ¯æ¯è¾ç®åçï¼æ ¸å¿å¨äºèªå®ä¹æç»çç¥åé»å¡éåã妿¤ä¸æ¥ï¼ä¸æ¦æä»¬ççº¿ç¨æ± ä¸çº¿ç¨è¾¾å°æ»¡è½½æ¶ï¼æä»¬å°±å¯ä»¥éè¿æç»çç¥å°ææ°ä»»å¡æä¹
åå° MySQL æ°æ®åºä¸ï¼çå°çº¿ç¨æ± æäºæä½åå¤çææä»»å¡æ¶ï¼è®©å
¶ä¼å
å¤çæ°æ®åºä¸çä»»å¡ä»¥é¿å
"饥饿"é®é¢ã
å½ç¶ï¼å¯¹äºè¿ä¸ªé®é¢ï¼æä»¬ä¹å¯ä»¥åèå
¶ä»ä¸»æµæ¡æ¶çåæ³ï¼ä»¥ Netty 为ä¾ï¼å®çæç»çç¥åæ¯ç´æ¥å建ä¸ä¸ªçº¿ç¨æ± 以å¤ç线ç¨å¤çè¿äºä»»å¡ï¼ä¸ºäºä¿è¯ä»»å¡ç宿¶å¤çï¼è¿ç§åæ³å¯è½éè¦è¯å¥½ç硬件设å¤ä¸ä¸´æ¶å建ççº¿ç¨æ æ³åå°åç¡®ççæ§ï¼
```java
private static final class NewThreadRunsPolicy implements RejectedExecutionHandler {
NewThreadRunsPolicy() {
super();
}
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
//å建ä¸ä¸ªä¸´æ¶çº¿ç¨å¤çä»»å¡
final Thread t = new Thread(r, "Temporary task executor");
t.start();
} catch (Throwable e) {
throw new RejectedExecutionException(
"Failed to start a new thread", e);
}
}
}
```
ActiveMQ 忝å°è¯å¨æå®çæ¶æå
å°½å¯è½çäºåå°ä»»å¡å
¥éï¼ä»¥ä¿è¯æå¤§äº¤ä»ï¼
```java
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
try {
//éæ¶é»å¡çå¾
ï¼å®ç°å°½å¯è½äº¤ä»
executor.getQueue().offer(r, 60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RejectedExecutionException("Interrupted waiting for BrokerService.worker");
}
throw new RejectedExecutionException("Timed Out while attempting to enqueue Task.");
}
});
```
### çº¿ç¨æ± 常ç¨çé»å¡éåæåªäºï¼
æ°ä»»å¡æ¥çæ¶åä¼å
夿å½åè¿è¡ççº¿ç¨æ°éæ¯å¦è¾¾å°æ ¸å¿çº¿ç¨æ°ï¼å¦æè¾¾å°çè¯ï¼æ°ä»»å¡å°±ä¼è¢«åæ¾å¨éåä¸ã
ä¸åççº¿ç¨æ± ä¼éç¨ä¸åçé»å¡éåï¼æä»¬å¯ä»¥ç»åå
ç½®çº¿ç¨æ± æ¥åæã
- 容é为 `Integer.MAX_VALUE` ç `LinkedBlockingQueue`ï¼æ çé»å¡éåï¼ï¼`FixedThreadPool` å `SingleThreadExecutor` ã`FixedThreadPool`æå¤åªè½åå»ºæ ¸å¿çº¿ç¨æ°ç线ç¨ï¼æ ¸å¿çº¿ç¨æ°åæå¤§çº¿ç¨æ°ç¸çï¼ï¼`SingleThreadExecutor`åªè½å建ä¸ä¸ªçº¿ç¨ï¼æ ¸å¿çº¿ç¨æ°åæå¤§çº¿ç¨æ°é½æ¯ 1ï¼ï¼äºè
çä»»å¡éåæ°¸è¿ä¸ä¼è¢«æ¾æ»¡ã
- `SynchronousQueue`ï¼åæ¥éåï¼ï¼`CachedThreadPool` ã`SynchronousQueue` 没æå®¹éï¼ä¸åå¨å
ç´ ï¼ç®çæ¯ä¿è¯å¯¹äºæäº¤çä»»å¡ï¼å¦ææç©ºé²çº¿ç¨ï¼å使ç¨ç©ºé²çº¿ç¨æ¥å¤çï¼å¦åæ°å»ºä¸ä¸ªçº¿ç¨æ¥å¤çä»»å¡ãä¹å°±æ¯è¯´ï¼`CachedThreadPool` çæå¤§çº¿ç¨æ°æ¯ `Integer.MAX_VALUE` ï¼å¯ä»¥çè§£ä¸ºçº¿ç¨æ°æ¯å¯ä»¥æ éæ©å±çï¼å¯è½ä¼å建大é线ç¨ï¼ä»èå¯¼è´ OOMã
- `DelayedWorkQueue`ï¼å»¶è¿éåï¼ï¼`ScheduledThreadPool` å `SingleThreadScheduledExecutor` ã`DelayedWorkQueue` çå
é¨å
ç´ å¹¶ä¸æ¯æç
§æ¾å
¥çæ¶é´æåºï¼èæ¯ä¼æç
§å»¶è¿çæ¶é´é¿ç对任å¡è¿è¡æåºï¼å
é¨éç¨çæ¯âå âçæ°æ®ç»æï¼å¯ä»¥ä¿è¯æ¯æ¬¡åºéçä»»å¡é½æ¯å½åéå䏿§è¡æ¶é´æé åçã`DelayedWorkQueue` æ·»å å
ç´ æ»¡äºä¹åä¼èªå¨æ©å®¹ï¼å¢å 忥容éç 50%ï¼å³æ°¸è¿ä¸ä¼é»å¡ï¼æå¤§æ©å®¹å¯è¾¾ `Integer.MAX_VALUE`ï¼æä»¥æå¤åªè½åå»ºæ ¸å¿çº¿ç¨æ°ç线ç¨ã
- `ArrayBlockingQueue`ï¼æçé»å¡éåï¼ï¼åºå±ç±æ°ç»å®ç°ï¼å®¹é䏿¦å建ï¼å°±ä¸è½ä¿®æ¹ã
### âï¸çº¿ç¨æ± å¤çä»»å¡çæµç¨äºè§£åï¼

1. 妿å½åè¿è¡ççº¿ç¨æ°å°äºæ ¸å¿çº¿ç¨æ°ï¼é£ä¹å°±ä¼æ°å»ºä¸ä¸ªçº¿ç¨æ¥æ§è¡ä»»å¡ã
2. 妿å½åè¿è¡ççº¿ç¨æ°çäºæå¤§äºæ ¸å¿çº¿ç¨æ°ï¼ä½æ¯å°äºæå¤§çº¿ç¨æ°ï¼é£ä¹å°±æè¯¥ä»»å¡æ¾å
¥å°ä»»å¡éåéçå¾
æ§è¡ã
3. 妿åä»»å¡éåææ¾ä»»å¡å¤±è´¥ï¼ä»»å¡éåå·²ç»æ»¡äºï¼ï¼ä½æ¯å½åè¿è¡ççº¿ç¨æ°æ¯å°äºæå¤§çº¿ç¨æ°çï¼å°±æ°å»ºä¸ä¸ªçº¿ç¨æ¥æ§è¡ä»»å¡ã
4. 妿å½åè¿è¡ççº¿ç¨æ°å·²ç»çåäºæå¤§çº¿ç¨æ°äºï¼æ°å»ºçº¿ç¨å°ä¼ä½¿å½åè¿è¡ç线ç¨è¶
åºæå¤§çº¿ç¨æ°ï¼é£ä¹å½åä»»å¡ä¼è¢«æç»ï¼æç»çç¥ä¼è°ç¨`RejectedExecutionHandler.rejectedExecution()`æ¹æ³ã
åæä¸ä¸ªæææçå°é®é¢ï¼**çº¿ç¨æ± å¨æäº¤ä»»å¡åï¼å¯ä»¥æåå建线ç¨åï¼**
çæ¡æ¯å¯ä»¥çï¼`ThreadPoolExecutor` æä¾äºä¸¤ä¸ªæ¹æ³å¸®å©æä»¬å¨æäº¤ä»»å¡ä¹åï¼å®ææ ¸å¿çº¿ç¨çå建ï¼ä»èå®ç°çº¿ç¨æ± é¢ççææï¼
- `prestartCoreThread()`:å¯å¨ä¸ä¸ªçº¿ç¨ï¼çå¾
ä»»å¡ï¼å¦æå·²è¾¾å°æ ¸å¿çº¿ç¨æ°ï¼è¿ä¸ªæ¹æ³è¿å falseï¼å¦åè¿å trueï¼
- `prestartAllCoreThreads()`:å¯å¨ææçæ ¸å¿çº¿ç¨ï¼å¹¶è¿åå¯å¨æåçæ ¸å¿çº¿ç¨æ°ã
### âï¸çº¿ç¨æ± ä¸çº¿ç¨å¼å¸¸åï¼éæ¯è¿æ¯å¤ç¨ï¼
ç´æ¥è¯´ç»è®ºï¼éè¦åä¸¤ç§æ
åµï¼
- **使ç¨`execute()`æäº¤ä»»å¡**ï¼å½ä»»å¡éè¿`execute()`æäº¤å°çº¿ç¨æ± 并卿§è¡è¿ç¨ä¸æåºå¼å¸¸æ¶ï¼å¦æè¿ä¸ªå¼å¸¸æ²¡æå¨ä»»å¡å
被æè·ï¼é£ä¹è¯¥å¼å¸¸ä¼å¯¼è´å½å线ç¨ç»æ¢ï¼å¹¶ä¸å¼å¸¸ä¼è¢«æå°å°æ§å¶å°ææ¥å¿æä»¶ä¸ãçº¿ç¨æ± 伿£æµå°è¿ç§çº¿ç¨ç»æ¢ï¼å¹¶å建ä¸ä¸ªæ°çº¿ç¨æ¥æ¿æ¢å®ï¼ä»èä¿æé
ç½®ççº¿ç¨æ°ä¸åã
- **使ç¨`submit()`æäº¤ä»»å¡**ï¼å¯¹äºéè¿`submit()`æäº¤çä»»å¡ï¼å¦æå¨ä»»å¡æ§è¡ä¸åçå¼å¸¸ï¼è¿ä¸ªå¼å¸¸ä¸ä¼ç´æ¥æå°åºæ¥ãç¸åï¼å¼å¸¸ä¼è¢«å°è£
å¨ç±`submit()`è¿åç`Future`对象ä¸ãå½è°ç¨`Future.get()`æ¹æ³æ¶ï¼å¯ä»¥æè·å°ä¸ä¸ª`ExecutionException`ãå¨è¿ç§æ
åµä¸ï¼çº¿ç¨ä¸ä¼å 为å¼å¸¸èç»æ¢ï¼å®ä¼ç»§ç»åå¨äºçº¿ç¨æ± ä¸ï¼å夿§è¡åç»çä»»å¡ã
ç®åæ¥è¯´ï¼ä½¿ç¨`execute()`æ¶ï¼æªæè·å¼å¸¸å¯¼è´çº¿ç¨ç»æ¢ï¼çº¿ç¨æ± å建æ°çº¿ç¨æ¿ä»£ï¼ä½¿ç¨`submit()`æ¶ï¼å¼å¸¸è¢«å°è£
å¨`Future`ä¸ï¼çº¿ç¨ç»§ç»å¤ç¨ã
è¿ç§è®¾è®¡å
许`submit()`æä¾æ´çµæ´»çé误å¤çæºå¶ï¼å 为å®å
许è°ç¨è
å³å®å¦ä½å¤çå¼å¸¸ï¼è`execute()`åéç¨äºé£äºä¸éè¦å
³æ³¨æ§è¡ç»æçåºæ¯ã
å
·ä½çæºç åæå¯ä»¥åèè¿ç¯ï¼[çº¿ç¨æ± ä¸çº¿ç¨å¼å¸¸åï¼éæ¯è¿æ¯å¤ç¨ï¼ - äº¬ä¸ææ¯](https://mp.weixin.qq.com/s/9ODjdUU-EwQFF5PrnzOGfw)ã
### âï¸å¦ä½ç»çº¿ç¨æ± å½åï¼
åå§åçº¿ç¨æ± çæ¶åéè¦æ¾ç¤ºå½åï¼è®¾ç½®çº¿ç¨æ± åç§°åç¼ï¼ï¼æå©äºå®ä½é®é¢ã
é»è®¤æ
åµä¸å建ç线ç¨åå类似 `pool-1-thread-n` è¿æ ·çï¼æ²¡æä¸å¡å«ä¹ï¼ä¸å©äºæä»¬å®ä½é®é¢ã
ç»çº¿ç¨æ± éç线ç¨å½åé常æä¸é¢ä¸¤ç§æ¹å¼ï¼
**1ãå©ç¨ guava ç `ThreadFactoryBuilder`**
```java
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat(threadNamePrefix + "-%d")
.setDaemon(true).build();
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
```
**2ãèªå·±å®ç° `ThreadFactory`ã**
```java
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线ç¨å·¥åï¼å®è®¾ç½®çº¿ç¨åç§°ï¼æå©äºæä»¬å®ä½é®é¢ã
*/
public final class NamingThreadFactory implements ThreadFactory {
private final AtomicInteger threadNum = new AtomicInteger();
private final String name;
/**
* å建ä¸ä¸ªå¸¦ååççº¿ç¨æ± ç产工å
*/
public NamingThreadFactory(String name) {
this.name = name;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName(name + " [#" + threadNum.incrementAndGet() + "]");
return t;
}
}
```
### å¦ä½è®¾å®çº¿ç¨æ± ç大å°ï¼
å¾å¤äººçè³å¯è½é½ä¼è§å¾æçº¿ç¨æ± é
ç½®è¿å¤§ä¸ç¹æ¯è¾å¥½ï¼æè§å¾è¿ææ¾æ¯æé®é¢çãå°±æ¿æä»¬çæ´»ä¸é常常è§çä¸ä¾åæ¥è¯´ï¼**并䏿¯äººå¤å°±è½æäºæ
å好ï¼å¢å äºæ²éäº¤æµææ¬ãä½ æ¬æ¥ä¸ä»¶äºæ
åªéè¦ 3 个人åï¼ä½ ç¡¬æ¯ææ¥äº 6 个人ï¼ä¼æååäºæçåï¼ææ³å¹¶ä¸ä¼ã** çº¿ç¨æ°éè¿å¤çå½±å乿¯åæä»¬åé
å¤å°äººåäºæ
䏿 ·ï¼å¯¹äºå¤çº¿ç¨è¿ä¸ªåºæ¯æ¥è¯´ä¸»è¦æ¯å¢å äº**ä¸ä¸æåæ¢**ææ¬ã䏿¸
æ¥ä»ä¹æ¯ä¸ä¸æåæ¢çè¯ï¼å¯ä»¥çæä¸é¢çä»ç»ã
> ä¸ä¸æåæ¢ï¼
>
> å¤çº¿ç¨ç¼ç¨ä¸ä¸è¬çº¿ç¨ç个æ°é½å¤§äº CPU æ ¸å¿ç个æ°ï¼èä¸ä¸ª CPU æ ¸å¿å¨ä»»ææ¶å»åªè½è¢«ä¸ä¸ªçº¿ç¨ä½¿ç¨ï¼ä¸ºäºè®©è¿äºçº¿ç¨é½è½å¾å°æææ§è¡ï¼CPU éåççç¥æ¯ä¸ºæ¯ä¸ªçº¿ç¨åé
æ¶é´ç并轮转çå½¢å¼ãå½ä¸ä¸ªçº¿ç¨çæ¶é´çç¨å®çæ¶åå°±ä¼éæ°å¤äºå°±ç»ªç¶æè®©ç»å
¶ä»çº¿ç¨ä½¿ç¨ï¼è¿ä¸ªè¿ç¨å°±å±äºä¸æ¬¡ä¸ä¸æåæ¢ãæ¦æ¬æ¥è¯´å°±æ¯ï¼å½åä»»å¡å¨æ§è¡å® CPU æ¶é´ç忢å°å¦ä¸ä¸ªä»»å¡ä¹åä¼å
ä¿åèªå·±çç¶æï¼ä»¥ä¾¿ä¸æ¬¡å忢åè¿ä¸ªä»»å¡æ¶ï¼å¯ä»¥åå è½½è¿ä¸ªä»»å¡çç¶æã**ä»»å¡ä»ä¿åå°åå è½½çè¿ç¨å°±æ¯ä¸æ¬¡ä¸ä¸æåæ¢**ã
>
> ä¸ä¸æåæ¢é常æ¯è®¡ç®å¯éåçãä¹å°±æ¯è¯´ï¼å®éè¦ç¸å½å¯è§çå¤ç卿¶é´ï¼å¨æ¯ç§å åä¸ç¾æ¬¡ç忢ä¸ï¼æ¯æ¬¡åæ¢é½éè¦çº³ç§éçº§çæ¶é´ãæä»¥ï¼ä¸ä¸æåæ¢å¯¹ç³»ç»æ¥è¯´æå³çæ¶è大éç CPU æ¶é´ï¼äºå®ä¸ï¼å¯è½æ¯æä½ç³»ç»ä¸æ¶é´æ¶èæå¤§çæä½ã
>
> Linux ç¸æ¯ä¸å
¶ä»æä½ç³»ç»ï¼å
æ¬å
¶ä»ç±» Unix ç³»ç»ï¼æå¾å¤çä¼ç¹ï¼å
¶ä¸æä¸é¡¹å°±æ¯ï¼å
¶ä¸ä¸æåæ¢å模å¼åæ¢çæ¶é´æ¶èé常å°ã
ç±»æ¯äºç°å®ä¸çä¸ç人类éè¿åä½åæä»¶äºæ
ï¼æä»¬å¯ä»¥è¯å®çä¸ç¹æ¯çº¿ç¨æ± 大å°è®¾ç½®è¿å¤§æè
è¿å°é½ä¼æé®é¢ï¼åéçææ¯æå¥½ã
- 妿æä»¬è®¾ç½®ççº¿ç¨æ± æ°é太å°çè¯ï¼å¦æå䏿¶é´æå¤§éä»»å¡/请æ±éè¦å¤çï¼å¯è½ä¼å¯¼è´å¤§éç请æ±/ä»»å¡å¨ä»»å¡éå䏿éçå¾
æ§è¡ï¼çè³ä¼åºç°ä»»å¡éåæ»¡äºä¹åä»»å¡/è¯·æ±æ æ³å¤ççæ
åµï¼æè
大éä»»å¡å 积å¨ä»»å¡éåå¯¼è´ OOMãè¿æ ·å¾ææ¾æ¯æé®é¢çï¼CPU æ ¹æ¬æ²¡æå¾å°å
åå©ç¨ã
- 妿æä»¬è®¾ç½®çº¿ç¨æ°é太大ï¼å¤§é线ç¨å¯è½ä¼åæ¶å¨äºå CPU èµæºï¼è¿æ ·ä¼å¯¼è´å¤§éçä¸ä¸æåæ¢ï¼ä»èå¢å 线ç¨çæ§è¡æ¶é´ï¼å½±åäºæ´ä½æ§è¡æçã
æä¸ä¸ªç®åå¹¶ä¸éç¨é¢æ¯è¾å¹¿çå
¬å¼ï¼
- **CPU å¯éåä»»å¡(N+1)ï¼** è¿ç§ä»»å¡æ¶èçä¸»è¦æ¯ CPU èµæºï¼å¯ä»¥å°çº¿ç¨æ°è®¾ç½®ä¸º Nï¼CPU æ ¸å¿æ°ï¼+1ãæ¯ CPU æ ¸å¿æ°å¤åºæ¥çä¸ä¸ªçº¿ç¨æ¯ä¸ºäºé²æ¢çº¿ç¨å¶åçç¼ºé¡µä¸æï¼æè
å
¶å®åå 导è´ç任塿åè带æ¥çå½±åã䏿¦ä»»å¡æåï¼CPU å°±ä¼å¤äºç©ºé²ç¶æï¼èå¨è¿ç§æ
åµä¸å¤åºæ¥çä¸ä¸ªçº¿ç¨å°±å¯ä»¥å
åå©ç¨ CPU çç©ºé²æ¶é´ã
- **I/O å¯éåä»»å¡(2N)ï¼** è¿ç§ä»»å¡åºç¨èµ·æ¥ï¼ç³»ç»ä¼ç¨å¤§é¨åçæ¶é´æ¥å¤ç I/O 交äºï¼è线ç¨å¨å¤ç I/O çæ¶é´æ®µå
ä¸ä¼å ç¨ CPU æ¥å¤çï¼è¿æ¶å°±å¯ä»¥å° CPU 交åºç»å
¶å®çº¿ç¨ä½¿ç¨ãå æ¤å¨ I/O å¯éåä»»å¡çåºç¨ä¸ï¼æä»¬å¯ä»¥å¤é
ç½®ä¸äºçº¿ç¨ï¼å
·ä½çè®¡ç®æ¹æ³æ¯ 2Nã
**å¦ä½å¤ææ¯ CPU å¯éä»»å¡è¿æ¯ IO å¯éä»»å¡ï¼**
CPU å¯éåç®åç解就æ¯å©ç¨ CPU 计ç®è½åç任塿¯å¦ä½ å¨å
åä¸å¯¹å¤§éæ°æ®è¿è¡æåºãä½å¡æ¶åå°ç½ç»è¯»åï¼æä»¶è¯»åè¿ç±»é½æ¯ IO å¯éåï¼è¿ç±»ä»»å¡çç¹ç¹æ¯ CPU 计ç®èè´¹æ¶é´ç¸æ¯äºçå¾
IO æä½å®æçæ¶é´æ¥è¯´å¾å°ï¼å¤§é¨åæ¶é´é½è±å¨äºçå¾
IO æä½å®æä¸ã
> ð æå±ä¸ä¸ï¼åè§ï¼[issue#1737](https://github.com/Snailclimb/JavaGuide/issues/1737)ï¼ï¼
>
> çº¿ç¨æ°æ´ä¸¥è°¨ç计ç®çæ¹æ³åºè¯¥æ¯ï¼`æä½³çº¿ç¨æ° = Nï¼CPU æ ¸å¿æ°ï¼âï¼1+WTï¼çº¿ç¨çå¾
æ¶é´ï¼/STï¼çº¿ç¨è®¡ç®æ¶é´ï¼ï¼`ï¼å
¶ä¸ `WTï¼çº¿ç¨çå¾
æ¶é´ï¼=线ç¨è¿è¡æ»æ¶é´ - STï¼çº¿ç¨è®¡ç®æ¶é´ï¼`ã
>
> 线ç¨çå¾
æ¶é´æå æ¯ä¾è¶é«ï¼éè¦è¶å¤çº¿ç¨ã线ç¨è®¡ç®æ¶é´æå æ¯ä¾è¶é«ï¼éè¦è¶å°çº¿ç¨ã
>
> æä»¬å¯ä»¥éè¿ JDK èªå¸¦çå·¥å
· VisualVM æ¥æ¥ç `WT/ST` æ¯ä¾ã
>
> CPU å¯éåä»»å¡ç `WT/ST` æ¥è¿æè
çäº 0ï¼å æ¤ï¼ çº¿ç¨æ°å¯ä»¥è®¾ç½®ä¸º Nï¼CPU æ ¸å¿æ°ï¼âï¼1+0ï¼= Nï¼åæä»¬ä¸é¢è¯´ç Nï¼CPU æ ¸å¿æ°ï¼+1 å·®ä¸å¤ã
>
> IO å¯éåä»»å¡ä¸ï¼å ä¹å
¨æ¯çº¿ç¨çå¾
æ¶é´ï¼ä»çè®ºä¸æ¥è¯´ï¼ä½ å°±å¯ä»¥å°çº¿ç¨æ°è®¾ç½®ä¸º 2Nï¼æéçæ¥è¯´ï¼WT/ST çç»æåºè¯¥æ¯è¾å¤§ï¼è¿ééæ© 2N çåå åºè¯¥æ¯ä¸ºäºé¿å
å建è¿å¤çº¿ç¨å§ï¼ã
å
¬å¼ä¹åªæ¯åèï¼å
·ä½è¿æ¯è¦æ ¹æ®é¡¹ç®å®é
线ä¸è¿è¡æ
嵿¥å¨æè°æ´ãæå¨åé¢ä»ç»çç¾å¢ççº¿ç¨æ± 忰卿é
ç½®è¿ç§æ¹æ¡å°±é常ä¸éï¼å¾å®ç¨ï¼
### âï¸å¦ä½å¨æä¿®æ¹çº¿ç¨æ± çåæ°ï¼
ç¾å¢ææ¯å¢éå¨[ãJava çº¿ç¨æ± å®ç°åçåå
¶å¨ç¾å¢ä¸å¡ä¸çå®è·µã](https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html)è¿ç¯æç« ä¸ä»ç»å°å¯¹çº¿ç¨æ± åæ°å®ç°å¯èªå®ä¹é
ç½®çæè·¯åæ¹æ³ã
ç¾å¢ææ¯å¢éçæè·¯æ¯ä¸»è¦å¯¹çº¿ç¨æ± çæ ¸å¿åæ°å®ç°èªå®ä¹å¯é
ç½®ãè¿ä¸ä¸ªæ ¸å¿åæ°æ¯ï¼
- **`corePoolSize` :** æ ¸å¿çº¿ç¨æ°å®ä¹äºæå°å¯ä»¥åæ¶è¿è¡ççº¿ç¨æ°éã
- **`maximumPoolSize` :** å½éåä¸åæ¾çä»»å¡è¾¾å°éå容éçæ¶åï¼å½åå¯ä»¥åæ¶è¿è¡ççº¿ç¨æ°éå为æå¤§çº¿ç¨æ°ã
- **`workQueue`:** 彿°ä»»å¡æ¥çæ¶åä¼å
夿å½åè¿è¡ççº¿ç¨æ°éæ¯å¦è¾¾å°æ ¸å¿çº¿ç¨æ°ï¼å¦æè¾¾å°çè¯ï¼æ°ä»»å¡å°±ä¼è¢«åæ¾å¨éåä¸ã
**为ä»ä¹æ¯è¿ä¸ä¸ªåæ°ï¼**
æå¨[Java çº¿ç¨æ± 详解](https://javaguide.cn/java/concurrent/java-thread-pool-summary.html) è¿ç¯æç« ä¸å°±è¯´è¿è¿ä¸ä¸ªåæ°æ¯ `ThreadPoolExecutor` æéè¦çåæ°ï¼å®ä»¬åºæ¬å³å®äºçº¿ç¨æ± 对äºä»»å¡çå¤ççç¥ã
**å¦ä½æ¯æåæ°å¨æé
ç½®ï¼** ä¸ç `ThreadPoolExecutor` æä¾çä¸é¢è¿äºæ¹æ³ã

æ ¼å¤éè¦æ³¨æçæ¯`corePoolSize`ï¼ ç¨åºè¿è¡æé´çæ¶åï¼æä»¬è°ç¨ `setCorePoolSize()`è¿ä¸ªæ¹æ³çè¯ï¼çº¿ç¨æ± ä¼é¦å
夿å½åå·¥ä½çº¿ç¨æ°æ¯å¦å¤§äº`corePoolSize`ï¼å¦æå¤§äºçè¯å°±ä¼åæ¶å·¥ä½çº¿ç¨ã
å¦å¤ï¼ä½ ä¹çå°äºä¸é¢å¹¶æ²¡æå¨ææå®éåé¿åº¦çæ¹æ³ï¼ç¾å¢çæ¹å¼æ¯èªå®ä¹äºä¸ä¸ªå«å `ResizableCapacityLinkedBlockIngQueue` çéåï¼ä¸»è¦å°±æ¯æ`LinkedBlockingQueue`ç capacity åæ®µç final å
³é®å修饰ç»å»æäºï¼è®©å®å为å¯åçï¼ã
æç»å®ç°çå¯å¨æä¿®æ¹çº¿ç¨æ± åæ°ææå¦ä¸ãððð

è¿æ²¡çå¤ï¼æå¨[ãå端é¢è¯é«é¢ç³»ç»è®¾è®¡&åºæ¯é¢ã](https://javaguide.cn/zhuanlan/back-end-interview-high-frequency-system-design-and-scenario-questions.html)ä¸è¯¦ç»ä»ç»äºå¦ä½è®¾è®¡ä¸ä¸ªå¨æçº¿ç¨æ± ï¼è¿ä¹æ¯é¢è¯ä¸å¸¸é®çä¸éç³»ç»è®¾è®¡é¢ã

妿æä»¬ç项ç®ä¹æ³è¦å®ç°è¿ç§ææçè¯ï¼å¯ä»¥åå©ç°æç弿ºé¡¹ç®ï¼
- **[Hippo4j](https://github.com/opengoofy/hippo4j)**ï¼å¼æ¥çº¿ç¨æ± æ¡æ¶ï¼æ¯æçº¿ç¨æ± 卿忴&çæ§&æ¥è¦ï¼æ éä¿®æ¹ä»£ç è½»æ¾å¼å
¥ãæ¯æå¤ç§ä½¿ç¨æ¨¡å¼ï¼è½»æ¾å¼å
¥ï¼è´åäºæé«ç³»ç»è¿è¡ä¿éè½åã
- **[Dynamic TP](https://github.com/dromara/dynamic-tp)**ï¼è½»éçº§å¨æçº¿ç¨æ± ï¼å
ç½®çæ§åè¦åè½ï¼éæä¸æ¹ä¸é´ä»¶çº¿ç¨æ± 管çï¼åºäºä¸»æµé
ç½®ä¸å¿ï¼å·²æ¯æ NacosãApolloï¼ZookeeperãConsulãEtcdï¼å¯éè¿ SPI èªå®ä¹å®ç°ï¼ã
### âï¸å¦ä½è®¾è®¡ä¸ä¸ªè½å¤æ ¹æ®ä»»å¡çä¼å
çº§æ¥æ§è¡ççº¿ç¨æ± ï¼
è¿æ¯ä¸ä¸ªå¸¸è§çé¢è¯é®é¢ï¼æ¬è´¨å
¶å®è¿æ¯å¨è坿±èè
对äºçº¿ç¨æ± 以åé»å¡éåçææ¡ã
æä»¬ä¸é¢ä¹æå°äºï¼ä¸åççº¿ç¨æ± ä¼éç¨ä¸åçé»å¡éåä½ä¸ºä»»å¡éåï¼æ¯å¦`FixedThreadPool` 使ç¨çæ¯`LinkedBlockingQueue`ï¼æçéåï¼ï¼é»è®¤æé å¨åå§çéåé¿åº¦ä¸º `Integer.MAX_VALUE` ï¼ç±äºéåæ°¸è¿ä¸ä¼è¢«æ¾æ»¡ï¼å æ¤`FixedThreadPool`æå¤åªè½åå»ºæ ¸å¿çº¿ç¨æ°ç线ç¨ã
å妿们éè¦å®ç°ä¸ä¸ªä¼å
级任å¡çº¿ç¨æ± çè¯ï¼é£å¯ä»¥èèä½¿ç¨ `PriorityBlockingQueue` ï¼ä¼å
级é»å¡éåï¼ä½ä¸ºä»»å¡éåï¼`ThreadPoolExecutor` çæé 彿°æä¸ä¸ª `workQueue` åæ°å¯ä»¥ä¼ å
¥ä»»å¡éåï¼ã

`PriorityBlockingQueue` æ¯ä¸ä¸ªæ¯æä¼å
çº§çæ çé»å¡éåï¼å¯ä»¥ç使¯çº¿ç¨å®å
¨ç `PriorityQueue`ï¼ä¸¤è
åºå±é½æ¯ä½¿ç¨å°é¡¶å å½¢å¼çäºåå ï¼å³å¼æå°çå
ç´ ä¼å
åºéãä¸è¿ï¼`PriorityQueue` 䏿¯æé»å¡æä½ã
è¦æ³è®© `PriorityBlockingQueue` å®ç°å¯¹ä»»å¡çæåºï¼ä¼ å
¥å
¶ä¸çä»»å¡å¿
é¡»æ¯å
·å¤æåºè½åçï¼æ¹å¼æä¸¤ç§ï¼
1. æäº¤å°çº¿ç¨æ± çä»»å¡å®ç° `Comparable` æ¥å£ï¼å¹¶éå `compareTo` æ¹æ³æ¥æå®ä»»å¡ä¹é´çä¼å
级æ¯è¾è§åã
2. å建 `PriorityBlockingQueue` æ¶ä¼ å
¥ä¸ä¸ª `Comparator` å¯¹è±¡æ¥æå®ä»»å¡ä¹é´çæåºè§å(æ¨è)ã
ä¸è¿ï¼è¿åå¨ä¸äºé£é©åé®é¢ï¼æ¯å¦ï¼
- `PriorityBlockingQueue` æ¯æ ççï¼å¯è½å 积大éç请æ±ï¼ä»èå¯¼è´ OOMã
- å¯è½ä¼å¯¼è´é¥¥é¥¿é®é¢ï¼å³ä½ä¼å
级çä»»å¡é¿æ¶é´å¾ä¸å°æ§è¡ã
- ç±äºéè¦å¯¹éåä¸çå
ç´ è¿è¡æåºæä½ä»¥åä¿è¯çº¿ç¨å®å
¨ï¼å¹¶åæ§å¶éç¨çæ¯å¯éå
¥é `ReentrantLock`ï¼ï¼å æ¤ä¼é使§è½ã
å¯¹äº OOM è¿ä¸ªé®é¢çè§£å³æ¯è¾ç®åç²æ´ï¼å°±æ¯ç»§æ¿`PriorityBlockingQueue` å¹¶éåä¸ä¸ `offer` æ¹æ³(å
¥é)çé»è¾ï¼å½æå
¥çå
ç´ æ°éè¶
è¿æå®å¼å°±è¿å false ã
饥饿é®é¢è¿ä¸ªå¯ä»¥éè¿ä¼å设计æ¥è§£å³ï¼æ¯è¾éº»ç¦ï¼ï¼æ¯å¦çå¾
æ¶é´è¿é¿çä»»å¡ä¼è¢«ç§»é¤å¹¶éæ°æ·»å å°éåä¸ï¼ä½æ¯ä¼å
级ä¼è¢«æåã
å¯¹äºæ§è½æ¹é¢çå½±åï¼æ¯æ²¡åæ³é¿å
çï¼æ¯ç«éè¦å¯¹ä»»å¡è¿è¡æåºæä½ãå¹¶ä¸ï¼å¯¹äºå¤§é¨åä¸å¡åºæ¯æ¥è¯´ï¼è¿ç¹æ§è½å½±åæ¯å¯ä»¥æ¥åçã
## Future
éç¹æ¯è¦ææ¡ `CompletableFuture` ç使ç¨ä»¥å常è§é¢è¯é¢ã
é¤äºä¸é¢çé¢è¯é¢ä¹å¤ï¼è¿æ¨èä½ ççæåçè¿ç¯æç« ï¼ [CompletableFuture 详解](https://javaguide.cn/java/concurrent/completablefuture-intro.html)ã
### Future ç±»æä»ä¹ç¨ï¼
`Future` ç±»æ¯å¼æ¥ææ³çå
¸åè¿ç¨ï¼ä¸»è¦ç¨å¨ä¸äºéè¦æ§è¡èæ¶ä»»å¡çåºæ¯ï¼é¿å
ç¨åºä¸ç´åå°çå¾
èæ¶ä»»å¡æ§è¡å®æï¼æ§è¡æç太ä½ãå
·ä½æ¥è¯´æ¯è¿æ ·çï¼å½æä»¬æ§è¡æä¸èæ¶ç任塿¶ï¼å¯ä»¥å°è¿ä¸ªèæ¶ä»»å¡äº¤ç»ä¸ä¸ªå线ç¨å»å¼æ¥æ§è¡ï¼åæ¶æä»¬å¯ä»¥å¹²ç¹å
¶ä»äºæ
ï¼ä¸ç¨å»å»çå¾
èæ¶ä»»å¡æ§è¡å®æãçæä»¬çäºæ
å¹²å®åï¼æä»¬åéè¿ `Future` ç±»è·åå°èæ¶ä»»å¡çæ§è¡ç»æãè¿æ ·ä¸æ¥ï¼ç¨åºçæ§è¡æçå°±ææ¾æé«äºã
è¿å
¶å®å°±æ¯å¤çº¿ç¨ä¸ç»å
¸ç **Future 模å¼**ï¼ä½ å¯ä»¥å°å
¶ç使¯ä¸ç§è®¾è®¡æ¨¡å¼ï¼æ ¸å¿ææ³æ¯å¼æ¥è°ç¨ï¼ä¸»è¦ç¨å¨å¤çº¿ç¨é¢åï¼å¹¶é Java è¯è¨ç¬æã
å¨ Java ä¸ï¼`Future` ç±»åªæ¯ä¸ä¸ªæ³åæ¥å£ï¼ä½äº `java.util.concurrent` å
ä¸ï¼å
¶ä¸å®ä¹äº 5 ä¸ªæ¹æ³ï¼ä¸»è¦å
æ¬ä¸é¢è¿ 4 个åè½ï¼
- åæ¶ä»»å¡ï¼
- 夿任塿¯å¦è¢«åæ¶;
- 夿任塿¯å¦å·²ç»æ§è¡å®æ;
- è·å任塿§è¡ç»æã
```java
// V 代表äºFutureæ§è¡çä»»å¡è¿åå¼çç±»å
public interface Future {
// 忶任塿§è¡
// æååæ¶è¿å trueï¼å¦åè¿å false
boolean cancel(boolean mayInterruptIfRunning);
// 夿任塿¯å¦è¢«åæ¶
boolean isCancelled();
// 夿任塿¯å¦å·²ç»æ§è¡å®æ
boolean isDone();
// è·å任塿§è¡ç»æ
V get() throws InterruptedException, ExecutionException;
// æå®æ¶é´å
没æè¿å计ç®ç»æå°±æåº TimeOutException å¼å¸¸
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutExceptio
}
```
ç®åç解就æ¯ï¼ææä¸ä¸ªä»»å¡ï¼æäº¤ç»äº `Future` æ¥å¤çã任塿§è¡æé´æèªå·±å¯ä»¥å»å任使³åçäºæ
ãå¹¶ä¸ï¼å¨è¿æé´æè¿å¯ä»¥åæ¶ä»»å¡ä»¥åè·åä»»å¡çæ§è¡ç¶æã䏿®µæ¶é´ä¹åï¼æå°±å¯ä»¥ `Future` é£éç´æ¥ååºä»»å¡æ§è¡ç»æã
### Callable å Future æä»ä¹å
³ç³»ï¼
æä»¬å¯ä»¥éè¿ `FutureTask` æ¥çè§£ `Callable` å `Future` ä¹é´çå
³ç³»ã
`FutureTask` æä¾äº `Future` æ¥å£çåºæ¬å®ç°ï¼å¸¸ç¨æ¥å°è£
`Callable` å `Runnable`ï¼å
·æåæ¶ä»»å¡ãæ¥ç任塿¯å¦æ§è¡å®æä»¥åè·å任塿§è¡ç»æçæ¹æ³ã`ExecutorService.submit()` æ¹æ³è¿åçå
¶å®å°±æ¯ `Future` çå®ç°ç±» `FutureTask` ã
```java
Future submit(Callable task);
Future> submit(Runnable task);
```
`FutureTask` ä¸å
å®ç°äº `Future`æ¥å£ï¼è¿å®ç°äº`Runnable` æ¥å£ï¼å æ¤å¯ä»¥ä½ä¸ºä»»å¡ç´æ¥è¢«çº¿ç¨æ§è¡ã

`FutureTask` æä¸¤ä¸ªæé 彿°ï¼å¯ä¼ å
¥ `Callable` æè
`Runnable` 对象ãå®é
ä¸ï¼ä¼ å
¥ `Runnable` 对象ä¹ä¼å¨æ¹æ³å
é¨è½¬æ¢ä¸º`Callable` 对象ã
```java
public FutureTask(Callable callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
public FutureTask(Runnable runnable, V result) {
// éè¿éé
å¨RunnableAdapteræ¥å°Runnable对象runnableè½¬æ¢æCallable对象
this.callable = Executors.callable(runnable, result);
this.state = NEW;
}
```
`FutureTask`ç¸å½äºå¯¹`Callable` è¿è¡äºå°è£
ï¼ç®¡çç任塿§è¡çæ
åµï¼åå¨äº `Callable` ç `call` æ¹æ³ç任塿§è¡ç»æã
å
³äºæ´å¤ `Future` çæºç ç»èï¼å¯ä»¥èè¿ç¯ä¸åè§£æï¼åç徿¸
æ¥ï¼[Java æ¯å¦ä½å®ç° Future 模å¼çï¼ä¸å详解ï¼](https://juejin.cn/post/6844904199625375757)ã
### CompletableFuture ç±»æä»ä¹ç¨ï¼
`Future` å¨å®é
使ç¨è¿ç¨ä¸åå¨ä¸äºå±éæ§ï¼æ¯å¦ä¸æ¯æå¼æ¥ä»»å¡çç¼æç»åãè·å计ç®ç»æç `get()` æ¹æ³ä¸ºé»å¡è°ç¨ã
Java 8 æè¢«å¼å
¥`CompletableFuture` ç±»å¯ä»¥è§£å³`Future` çè¿äºç¼ºé·ã`CompletableFuture` é¤äºæä¾äºæ´ä¸ºå¥½ç¨å强大ç `Future` ç¹æ§ä¹å¤ï¼è¿æä¾äºå½æ°å¼ç¼ç¨ã弿¥ä»»å¡ç¼æç»åï¼å¯ä»¥å°å¤ä¸ªå¼æ¥ä»»å¡ä¸²èèµ·æ¥ï¼ç»æä¸ä¸ªå®æ´çé¾å¼è°ç¨ï¼çè½åã
ä¸é¢æä»¬æ¥ç®åçç `CompletableFuture` ç±»çå®ä¹ã
```java
public class CompletableFuture implements Future, CompletionStage {
}
```
å¯ä»¥çå°ï¼`CompletableFuture` åæ¶å®ç°äº `Future` å `CompletionStage` æ¥å£ã

`CompletionStage` æ¥å£æè¿°äºä¸ä¸ªå¼æ¥è®¡ç®çé¶æ®µãå¾å¤è®¡ç®å¯ä»¥åæå¤ä¸ªé¶æ®µææ¥éª¤ï¼æ¤æ¶å¯ä»¥éè¿å®å°æææ¥éª¤ç»åèµ·æ¥ï¼å½¢æå¼æ¥è®¡ç®çæµæ°´çº¿ã
`CompletionStage` æ¥å£ä¸çæ¹æ³æ¯è¾å¤ï¼`CompletableFuture` ç彿°å¼è½åå°±æ¯è¿ä¸ªæ¥å£èµäºçãä»è¿ä¸ªæ¥å£çæ¹æ³åæ°ä½ å°±å¯ä»¥åç°å
¶å¤§é使ç¨äº Java8 å¼å
¥ç彿°å¼ç¼ç¨ã

### âï¸ä¸ä¸ªä»»å¡éè¦ä¾èµå¦å¤ä¸¤ä¸ªä»»å¡æ§è¡å®ä¹ååæ§è¡ï¼æä¹è®¾è®¡ï¼
è¿ç§ä»»å¡ç¼æåºæ¯é常éåéè¿`CompletableFuture`å®ç°ãè¿éå设è¦å®ç° T3 å¨ T2 å T1 æ§è¡å®åæ§è¡ã
代ç å¦ä¸ï¼è¿é为äºç®å代ç ï¼ç¨å°äº Hutool ç线ç¨å·¥å
·ç±» `ThreadUtil` åæ¥ææ¶é´å·¥å
·ç±» `DateUtil`ï¼ï¼
```java
// T1
CompletableFuture futureT1 = CompletableFuture.runAsync(() -> {
System.out.println("T1 is executing. Current timeï¼" + DateUtil.now());
// 模æèæ¶æä½
ThreadUtil.sleep(1000);
});
// T2
CompletableFuture futureT2 = CompletableFuture.runAsync(() -> {
System.out.println("T2 is executing. Current timeï¼" + DateUtil.now());
ThreadUtil.sleep(1000);
});
// 使ç¨allOf()æ¹æ³åå¹¶T1åT2çCompletableFutureï¼çå¾
å®ä»¬é½å®æ
CompletableFuture bothCompleted = CompletableFuture.allOf(futureT1, futureT2);
// å½T1åT2é½å®æåï¼æ§è¡T3
bothCompleted.thenRunAsync(() -> System.out.println("T3 is executing after T1 and T2 have completed.Current timeï¼" + DateUtil.now()));
// çå¾
ææä»»å¡å®æï¼éªè¯ææ
ThreadUtil.sleep(3000);
```
éè¿ `CompletableFuture` ç `allOf()` è¿ä¸ªéææ¹æ³æ¥å¹¶è¡è¿è¡ T1 å T2ï¼å½ T1 å T2 é½å®æåï¼åæ§è¡ T3ã
### âï¸ä½¿ç¨ CompletableFutureï¼æä¸ä¸ªä»»å¡å¤±è´¥ï¼å¦ä½å¤çå¼å¸¸ï¼
ä½¿ç¨ `CompletableFuture`çæ¶åä¸å®è¦ä»¥æ£ç¡®çæ¹å¼è¿è¡å¼å¸¸å¤çï¼é¿å
å¼å¸¸ä¸¢å¤±æè
åºç°ä¸å¯æ§é®é¢ã
ä¸é¢æ¯ä¸äºå»ºè®®ï¼
- ä½¿ç¨ `whenComplete` æ¹æ³å¯ä»¥å¨ä»»å¡å®ææ¶è§¦ååè°å½æ°ï¼å¹¶æ£ç¡®å°å¤çå¼å¸¸ï¼è䏿¯è®©å¼å¸¸è¢«å嬿䏢失ã
- ä½¿ç¨ `exceptionally` æ¹æ³å¯ä»¥å¤çå¼å¸¸å¹¶éæ°æåºï¼ä»¥ä¾¿å¼å¸¸è½å¤ä¼ æå°åç»é¶æ®µï¼è䏿¯è®©å¼å¸¸è¢«å¿½ç¥æç»æ¢ã
- ä½¿ç¨ `handle` æ¹æ³å¯ä»¥å¤çæ£å¸¸çè¿åç»æåå¼å¸¸ï¼å¹¶è¿åä¸ä¸ªæ°çç»æï¼è䏿¯è®©å¼å¸¸å½±åæ£å¸¸çä¸å¡é»è¾ã
- ä½¿ç¨ `CompletableFuture.allOf` æ¹æ³å¯ä»¥ç»åå¤ä¸ª `CompletableFuture`ï¼å¹¶ç»ä¸å¤çææä»»å¡çå¼å¸¸ï¼è䏿¯è®©å¼å¸¸å¤çè¿äºåé¿æéå¤ã
- â¦â¦
### âï¸å¨ä½¿ç¨ CompletableFuture çæ¶å为ä»ä¹è¦èªå®ä¹çº¿ç¨æ± ï¼
`CompletableFuture` é»è®¤ä½¿ç¨å
¨å±å
±äº«ç `ForkJoinPool.commonPool()` ä½ä¸ºæ§è¡å¨ï¼æææªæå®æ§è¡å¨ç弿¥ä»»å¡é½ä¼ä½¿ç¨è¯¥çº¿ç¨æ± ãè¿æå³çåºç¨ç¨åºãå¤ä¸ªåºææ¡æ¶ï¼å¦ Springãç¬¬ä¸æ¹åºï¼è¥é½ä¾èµ `CompletableFuture`ï¼é»è®¤æ
åµä¸å®ä»¬é½ä¼å
±äº«åä¸ä¸ªçº¿ç¨æ± ã
è½ç¶ `ForkJoinPool` æçå¾é«ï¼ä½å½åæ¶æäº¤å¤§é任塿¶ï¼å¯è½ä¼å¯¼è´èµæºç«äºå线ç¨é¥¥é¥¿ï¼è¿èå½±åç³»ç»æ§è½ã
为é¿å
è¿äºé®é¢ï¼å»ºè®®ä¸º `CompletableFuture` æä¾èªå®ä¹çº¿ç¨æ± ï¼å¸¦æ¥ä»¥ä¸ä¼å¿ï¼
- é离æ§ï¼ä¸ºä¸åä»»å¡åé
ç¬ç«ççº¿ç¨æ± ï¼é¿å
å
¨å±çº¿ç¨æ± èµæºäºå¤ºã
- èµæºæ§å¶ï¼æ ¹æ®ä»»å¡ç¹æ§è°æ´çº¿ç¨æ± 大å°åéåç±»åï¼ä¼åæ§è½è¡¨ç°ã
- å¼å¸¸å¤çï¼éè¿èªå®ä¹ `ThreadFactory` æ´å¥½å°å¤ç线ç¨ä¸çå¼å¸¸æ
åµã
```java
private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
CompletableFuture.runAsync(() -> {
//...
}, executor);
```
## AQS
å
³äº AQS æºç ç详ç»åæï¼å¯ä»¥ççè¿ä¸ç¯æç« ï¼[AQS 详解](https://javaguide.cn/java/concurrent/aqs.html)ã
### AQS æ¯ä»ä¹ï¼
AQS ï¼`AbstractQueuedSynchronizer` ï¼æ½è±¡éå忥å¨ï¼æ¯ä» JDK1.5 å¼å§æä¾ç Java å¹¶åæ ¸å¿ç»ä»¶ã
AQS è§£å³äºå¼åè
å¨å®ç°åæ¥å¨æ¶ç夿æ§é®é¢ã宿ä¾äºä¸ä¸ªéç¨æ¡æ¶ï¼ç¨äºå®ç°åç§åæ¥å¨ï¼ä¾å¦ **å¯éå
¥é**ï¼`ReentrantLock`ï¼ã**ä¿¡å·é**ï¼`Semaphore`ï¼å **å计æ¶å¨**ï¼`CountDownLatch`ï¼ãéè¿å°è£
åºå±ç线ç¨åæ¥æºå¶ï¼AQS å°å¤æç线ç¨ç®¡çé»è¾éèèµ·æ¥ï¼ä½¿å¼åè
åªé䏿³¨äºå
·ä½ç忥é»è¾ã
ç®åæ¥è¯´ï¼AQS æ¯ä¸ä¸ªæ½è±¡ç±»ï¼ä¸ºåæ¥å¨æä¾äºéç¨ç **æ§è¡æ¡æ¶**ãå®å®ä¹äº **èµæºè·ååéæ¾çéç¨æµç¨**ï¼èå
·ä½çèµæºè·åé»è¾åç±å
·ä½åæ¥å¨éè¿é忍¡æ¿æ¹æ³æ¥å®ç°ã å æ¤ï¼å¯ä»¥å° AQS ç使¯åæ¥å¨ç **åºç¡âåºåº§â**ï¼è忥å¨åæ¯åºäº AQS å®ç°ç **å
·ä½âåºç¨â**ã
### âï¸AQS çåçæ¯ä»ä¹ï¼
AQS æ ¸å¿ææ³æ¯ï¼å¦æè¢«è¯·æ±çå
±äº«èµæºç©ºé²ï¼åå°å½å请æ±èµæºç线ç¨è®¾ç½®ä¸ºææçå·¥ä½çº¿ç¨ï¼å¹¶ä¸å°å
±äº«èµæºè®¾ç½®ä¸ºéå®ç¶æãå¦æè¢«è¯·æ±çå
±äº«èµæºè¢«å ç¨ï¼é£ä¹å°±éè¦ä¸å¥çº¿ç¨é»å¡çå¾
以å被å¤éæ¶éåé
çæºå¶ï¼è¿ä¸ªæºå¶ AQS æ¯åºäº **CLH é** ï¼Craig, Landin, and Hagersten locksï¼ è¿ä¸æ¥ä¼åå®ç°çã
**CLH é** å¯¹èªæéè¿è¡äºæ¹è¿ï¼æ¯åºäºåé¾è¡¨çèªæéãå¨å¤çº¿ç¨åºæ¯ä¸ï¼ä¼å°è¯·æ±è·åéç线ç¨ç»ç»æä¸ä¸ªååéåï¼æ¯ä¸ªçå¾
ç线ç¨ä¼éè¿èªæè®¿é®åä¸ä¸ªçº¿ç¨èç¹çç¶æï¼åä¸ä¸ªèç¹éæ¾éä¹åï¼å½åèç¹æå¯ä»¥è·åéã**CLH é** çéåç»æå¦ä¸å¾æç¤ºã

AQS ä¸ä½¿ç¨ç **çå¾
éå** æ¯ CLH ééåçåä½ï¼æ¥ä¸æ¥ç®ç§°ä¸º CLH åä½éåï¼ã
AQS ç CLH åä½é忝ä¸ä¸ªååéåï¼ä¼ææ¶è·åä¸å°éç线ç¨å°è¢«å å
¥å°è¯¥éåä¸ï¼CLH åä½éåå忬ç CLH ééåçåºå«ä¸»è¦æä¸¤ç¹ï¼
- ç± **èªæ** ä¼å为 **èªæ + é»å¡** ï¼èªææä½çæ§è½å¾é«ï¼ä½å¤§éçèªææä½æ¯è¾å ç¨ CPU èµæºï¼å æ¤å¨ CLH åä½éåä¸ä¼å
éè¿èªæå°è¯è·åéï¼å¦æå¤±è´¥åè¿è¡é»å¡çå¾
ã
- ç± **ååéå** ä¼å为 **ååéå** ï¼å¨ CLH åä½éåä¸ï¼ä¼å¯¹çå¾
ç线ç¨è¿è¡é»å¡æä½ï¼å½éååè¾¹ç线ç¨éæ¾éä¹åï¼éè¦å¯¹åè¾¹ç线ç¨è¿è¡å¤éï¼å æ¤å¢å äº `next` æéï¼æä¸ºäºååéåã
AQS å°æ¯æ¡è¯·æ±å
±äº«èµæºç线ç¨å°è£
æä¸ä¸ª CLH åä½éåçä¸ä¸ªç»ç¹ï¼Nodeï¼æ¥å®ç°éçåé
ãå¨ CLH åä½éåä¸ï¼ä¸ä¸ªèç¹è¡¨ç¤ºä¸ä¸ªçº¿ç¨ï¼å®ä¿åç线ç¨çå¼ç¨ï¼threadï¼ã å½åèç¹å¨éåä¸çç¶æï¼waitStatusï¼ãå驱èç¹ï¼prevï¼ãåç»§èç¹ï¼nextï¼ã
AQS ä¸ç CLH åä½éåç»æå¦ä¸å¾æç¤ºï¼

AQS(`AbstractQueuedSynchronizer`)çæ ¸å¿åçå¾ï¼

AQS ä½¿ç¨ **int æååé `state` è¡¨ç¤ºåæ¥ç¶æ**ï¼éè¿å
ç½®ç **线ç¨çå¾
éå** æ¥å®æè·åèµæºçº¿ç¨çæéå·¥ä½ã
`state` åéç± `volatile` 修饰ï¼ç¨äºå±ç¤ºå½å临çèµæºçè·éæ
åµã
```java
// å
±äº«åéï¼ä½¿ç¨volatile修饰ä¿è¯çº¿ç¨å¯è§æ§
private volatile int state;
```
å¦å¤ï¼ç¶æä¿¡æ¯ `state` å¯ä»¥éè¿ `protected` ç±»åç`getState()`ã`setState()`å`compareAndSetState()` è¿è¡æä½ãå¹¶ä¸ï¼è¿å ä¸ªæ¹æ³é½æ¯ `final` 修饰çï¼å¨åç±»ä¸æ æ³è¢«éåã
```java
//è¿ååæ¥ç¶æçå½åå¼
protected final int getState() {
return state;
}
// è®¾ç½®åæ¥ç¶æçå¼
protected final void setState(int newState) {
state = newState;
}
//ååå°ï¼CASæä½ï¼å°åæ¥ç¶æå¼è®¾ç½®ä¸ºç»å®å¼update妿å½ååæ¥ç¶æçå¼çäºexpectï¼ææå¼ï¼
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
```
以 `ReentrantLock` 为ä¾ï¼`state` åå§å¼ä¸º 0ï¼è¡¨ç¤ºæªéå®ç¶æãA çº¿ç¨ `lock()` æ¶ï¼ä¼è°ç¨ `tryAcquire()` ç¬å 该éå¹¶å° `state+1` ãæ¤åï¼å
¶ä»çº¿ç¨å `tryAcquire()` æ¶å°±ä¼å¤±è´¥ï¼ç´å° A çº¿ç¨ `unlock()` å° `state=`0ï¼å³éæ¾éï¼ä¸ºæ¢ï¼å
¶å®çº¿ç¨æææºä¼è·å该éãå½ç¶ï¼éæ¾éä¹åï¼A 线ç¨èªå·±æ¯å¯ä»¥éå¤è·åæ¤éçï¼`state` ä¼ç´¯å ï¼ï¼è¿å°±æ¯å¯éå
¥çæ¦å¿µãä½è¦æ³¨æï¼è·åå¤å°æ¬¡å°±è¦éæ¾å¤å°æ¬¡ï¼è¿æ ·æè½ä¿è¯ state æ¯è½åå°é¶æçã
å以 `CountDownLatch` 以ä¾ï¼ä»»å¡å为 N 个å线ç¨å»æ§è¡ï¼`state` ä¹åå§å为 Nï¼æ³¨æ N è¦ä¸çº¿ç¨ä¸ªæ°ä¸è´ï¼ãè¿ N 个åçº¿ç¨æ¯å¹¶è¡æ§è¡çï¼æ¯ä¸ªåçº¿ç¨æ§è¡å®å`countDown()` 䏿¬¡ï¼state ä¼ CAS(Compare and Swap) å 1ãçå°ææå线ç¨é½æ§è¡å®å(å³ `state=0` )ï¼ä¼ `unpark()` 主è°ç¨çº¿ç¨ï¼ç¶å主è°ç¨çº¿ç¨å°±ä¼ä» `await()` 彿°è¿åï¼ç»§ç»åç»å¨ä½ã
### Semaphore æä»ä¹ç¨ï¼
`synchronized` å `ReentrantLock` 齿¯ä¸æ¬¡åªå
许ä¸ä¸ªçº¿ç¨è®¿é®æä¸ªèµæºï¼è`Semaphore`(ä¿¡å·é)å¯ä»¥ç¨æ¥æ§å¶åæ¶è®¿é®ç¹å®èµæºççº¿ç¨æ°éã
Semaphore ç使ç¨ç®åï¼æä»¬è¿éå设æ N(N>5) ä¸ªçº¿ç¨æ¥è·å `Semaphore` ä¸çå
±äº«èµæºï¼ä¸é¢ç代ç 表示å䏿¶å» N 个线ç¨ä¸åªæ 5 个线ç¨è½è·åå°å
±äº«èµæºï¼å
¶ä»çº¿ç¨é½ä¼é»å¡ï¼åªæè·åå°å
±äº«èµæºççº¿ç¨æè½æ§è¡ãçå°æçº¿ç¨éæ¾äºå
±äº«èµæºï¼å
¶ä»é»å¡ççº¿ç¨æè½è·åå°ã
```java
// åå§å
±äº«èµæºæ°é
final Semaphore semaphore = new Semaphore(5);
// è·å1个许å¯
semaphore.acquire();
// éæ¾1个许å¯
semaphore.release();
```
å½åå§çèµæºä¸ªæ°ä¸º 1 çæ¶åï¼`Semaphore` éå为æä»éã
`Semaphore` æä¸¤ç§æ¨¡å¼ï¼ã
- **å
¬å¹³æ¨¡å¼ï¼** è°ç¨ `acquire()` æ¹æ³ç顺åºå°±æ¯è·å许å¯è¯ç顺åºï¼éµå¾ª FIFOï¼
- **éå
¬å¹³æ¨¡å¼ï¼** æ¢å å¼çã
`Semaphore` 对åºç两个æé æ¹æ³å¦ä¸ï¼
```java
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
```
**è¿ä¸¤ä¸ªæé æ¹æ³ï¼é½å¿
é¡»æä¾è®¸å¯çæ°éï¼ç¬¬äºä¸ªæé æ¹æ³å¯ä»¥æå®æ¯å
¬å¹³æ¨¡å¼è¿æ¯éå
¬å¹³æ¨¡å¼ï¼é»è®¤éå
¬å¹³æ¨¡å¼ã**
`Semaphore` é常ç¨äºé£äºèµæºææç¡®è®¿é®æ°ééå¶çåºæ¯æ¯å¦éæµï¼ä»
éäºåæºæ¨¡å¼ï¼å®é
项ç®ä¸æ¨èä½¿ç¨ Redis +Lua æ¥åéæµï¼ã
### Semaphore çåçæ¯ä»ä¹ï¼
`Semaphore` æ¯å
±äº«éçä¸ç§å®ç°ï¼å®é»è®¤æé AQS ç `state` å¼ä¸º `permits`ï¼ä½ å¯ä»¥å° `permits` çå¼ç解为许å¯è¯çæ°éï¼åªææ¿å°è®¸å¯è¯ççº¿ç¨æè½æ§è¡ã
è°ç¨`semaphore.acquire()` ï¼çº¿ç¨å°è¯è·å许å¯è¯ï¼å¦æ `state >= 0` çè¯ï¼å表示å¯ä»¥è·åæåã妿è·åæåçè¯ï¼ä½¿ç¨ CAS æä½å»ä¿®æ¹ `state` çå¼ `state=state-1`ã妿 `state<0` çè¯ï¼å表示许å¯è¯æ°éä¸è¶³ãæ¤æ¶ä¼å建ä¸ä¸ª Node èç¹å å
¥é»å¡éåï¼æèµ·å½å线ç¨ã
```java
/**
* è·å1个许å¯è¯
*/
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* å
±äº«æ¨¡å¼ä¸è·å许å¯è¯ï¼è·åæååè¿åï¼å¤±è´¥åå å
¥é»å¡éåï¼æèµ·çº¿ç¨
*/
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// å°è¯è·å许å¯è¯ï¼arg为è·å许å¯è¯ä¸ªæ°ï¼å½å¯ç¨è®¸å¯è¯æ°åå½åè·åç许å¯è¯æ°ç»æå°äº0,åå建ä¸ä¸ªèç¹å å
¥é»å¡éåï¼æèµ·å½å线ç¨ã
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
```
è°ç¨`semaphore.release();` ï¼çº¿ç¨å°è¯éæ¾è®¸å¯è¯ï¼å¹¶ä½¿ç¨ CAS æä½å»ä¿®æ¹ `state` çå¼ `state=state+1`ãéæ¾è®¸å¯è¯æåä¹åï¼åæ¶ä¼å¤é忥éåä¸çä¸ä¸ªçº¿ç¨ã被å¤éç线ç¨ä¼éæ°å°è¯å»ä¿®æ¹ `state` çå¼ `state=state-1` ï¼å¦æ `state>=0` åè·å令çæåï¼å¦åéæ°è¿å
¥é»å¡éåï¼æèµ·çº¿ç¨ã
```java
// éæ¾ä¸ä¸ªè®¸å¯è¯
public void release() {
sync.releaseShared(1);
}
// éæ¾å
±äº«éï¼åæ¶ä¼å¤é忥éåä¸çä¸ä¸ªçº¿ç¨ã
public final boolean releaseShared(int arg) {
//éæ¾å
±äº«é
if (tryReleaseShared(arg)) {
//å¤é忥éåä¸çä¸ä¸ªçº¿ç¨
doReleaseShared();
return true;
}
return false;
}
```
### CountDownLatch æä»ä¹ç¨ï¼
`CountDownLatch` å
许 `count` 个线ç¨é»å¡å¨ä¸ä¸ªå°æ¹ï¼ç´è³ææçº¿ç¨çä»»å¡é½æ§è¡å®æ¯ã
`CountDownLatch` æ¯ä¸æ¬¡æ§çï¼è®¡æ°å¨çå¼åªè½å¨æé æ¹æ³ä¸åå§å䏿¬¡ï¼ä¹å没æä»»ä½æºå¶å次对å
¶è®¾ç½®å¼ï¼å½ `CountDownLatch` 使ç¨å®æ¯åï¼å®ä¸è½å次被使ç¨ã
### CountDownLatch çåçæ¯ä»ä¹ï¼
`CountDownLatch` æ¯å
±äº«éçä¸ç§å®ç°,å®é»è®¤æé AQS ç `state` å¼ä¸º `count`ãå½çº¿ç¨ä½¿ç¨ `countDown()` æ¹æ³æ¶,å
¶å®ä½¿ç¨äº`tryReleaseShared`æ¹æ³ä»¥ CAS çæä½æ¥åå° `state`,ç´è³ `state` 为 0 ãå½è°ç¨ `await()` æ¹æ³çæ¶åï¼å¦æ `state` ä¸ä¸º 0ï¼é£å°±è¯æä»»å¡è¿æ²¡ææ§è¡å®æ¯ï¼`await()` æ¹æ³å°±ä¼ä¸ç´é»å¡ï¼ä¹å°±æ¯è¯´ `await()` æ¹æ³ä¹åçè¯å¥ä¸ä¼è¢«æ§è¡ãç´å°`count` 个线ç¨è°ç¨äº`countDown()`使 state å¼è¢«å为 0ï¼æè
è°ç¨`await()`ç线ç¨è¢«ä¸æï¼è¯¥çº¿ç¨æä¼ä»é»å¡ä¸è¢«å¤éï¼`await()` æ¹æ³ä¹åçè¯å¥å¾å°æ§è¡ã
### ç¨è¿ CountDownLatch ä¹ï¼ä»ä¹åºæ¯ä¸ç¨çï¼
`CountDownLatch` çä½ç¨å°±æ¯ å
许 count 个线ç¨é»å¡å¨ä¸ä¸ªå°æ¹ï¼ç´è³ææçº¿ç¨çä»»å¡é½æ§è¡å®æ¯ãä¹åå¨é¡¹ç®ä¸ï¼æä¸ä¸ªä½¿ç¨å¤çº¿ç¨è¯»åå¤ä¸ªæä»¶å¤ççåºæ¯ï¼æç¨å°äº `CountDownLatch` ãå
·ä½åºæ¯æ¯ä¸é¢è¿æ ·çï¼
æä»¬è¦è¯»åå¤ç 6 个æä»¶ï¼è¿ 6 个任å¡é½æ¯æ²¡ææ§è¡é¡ºåºä¾èµçä»»å¡ï¼ä½æ¯æä»¬éè¦è¿åç»ç¨æ·çæ¶åå°è¿å 个æä»¶çå¤ççç»æè¿è¡ç»è®¡æ´çã
ä¸ºæ¤æä»¬å®ä¹äºä¸ä¸ªçº¿ç¨æ± å count 为 6 ç`CountDownLatch`对象 ã使ç¨çº¿ç¨æ± å¤ç读åä»»å¡ï¼æ¯ä¸ä¸ªçº¿ç¨å¤çå®ä¹åå°±å° count-1ï¼è°ç¨`CountDownLatch`对象ç `await()`æ¹æ³ï¼ç´å°æææä»¶è¯»åå®ä¹åï¼æä¼æ¥çæ§è¡åé¢çé»è¾ã
ä¼ªä»£ç æ¯ä¸é¢è¿æ ·çï¼
```java
public class CountDownLatchExample1 {
// å¤çæä»¶çæ°é
private static final int threadCount = 6;
public static void main(String[] args) throws InterruptedException {
// å建ä¸ä¸ªå
·æåºå®çº¿ç¨æ°éççº¿ç¨æ± å¯¹è±¡ï¼æ¨èä½¿ç¨æé æ¹æ³å建ï¼
ExecutorService threadPool = Executors.newFixedThreadPool(10);
final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int threadnum = i;
threadPool.execute(() -> {
try {
//å¤çæä»¶çä¸å¡æä½
//......
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//表示ä¸ä¸ªæä»¶å·²ç»è¢«å®æ
countDownLatch.countDown();
}
});
}
countDownLatch.await();
threadPool.shutdown();
System.out.println("finish");
}
}
```
**ææ²¡æå¯ä»¥æ¹è¿çå°æ¹å¢ï¼**
å¯ä»¥ä½¿ç¨ `CompletableFuture` ç±»æ¥æ¹è¿ï¼Java8 ç `CompletableFuture` æä¾äºå¾å¤å¯¹å¤çº¿ç¨åå¥½çæ¹æ³ï¼ä½¿ç¨å®å¯ä»¥å¾æ¹ä¾¿å°ä¸ºæä»¬ç¼åå¤çº¿ç¨ç¨åºï¼ä»ä¹å¼æ¥ã串è¡ãå¹¶è¡æè
çå¾
ææçº¿ç¨æ§è¡å®ä»»å¡ä»ä¹çé½é常æ¹ä¾¿ã
```java
CompletableFuture task1 =
CompletableFuture.supplyAsync(()->{
//èªå®ä¹ä¸å¡æä½
});
......
CompletableFuture task6 =
CompletableFuture.supplyAsync(()->{
//èªå®ä¹ä¸å¡æä½
});
......
CompletableFuture headerFuture=CompletableFuture.allOf(task1,.....,task6);
try {
headerFuture.join();
} catch (Exception ex) {
//......
}
System.out.println("all done. ");
```
ä¸é¢ç代ç è¿å¯ä»¥ç»§ç»ä¼åï¼å½ä»»å¡è¿å¤çæ¶åï¼ææ¯ä¸ä¸ª task é½ååºæ¥ä¸å¤ªç°å®ï¼å¯ä»¥èèéè¿å¾ªç¯æ¥æ·»å ä»»å¡ã
```java
//æä»¶å¤¹ä½ç½®
List filePaths = Arrays.asList(...)
// 弿¥å¤çæææä»¶
List> fileFutures = filePaths.stream()
.map(filePath -> doSomeThing(filePath))
.collect(Collectors.toList());
// å°ä»ä»¬åå¹¶èµ·æ¥
CompletableFuture allFutures = CompletableFuture.allOf(
fileFutures.toArray(new CompletableFuture[fileFutures.size()])
);
```
### CyclicBarrier æä»ä¹ç¨ï¼
`CyclicBarrier` å `CountDownLatch` é常类似ï¼å®ä¹å¯ä»¥å®ç°çº¿ç¨é´çææ¯çå¾
ï¼ä½æ¯å®çåè½æ¯ `CountDownLatch` æ´å 夿å强大ã主è¦åºç¨åºæ¯å `CountDownLatch` 类似ã
> `CountDownLatch` çå®ç°æ¯åºäº AQS çï¼è `CyclicBarrier` æ¯åºäº `ReentrantLock`(`ReentrantLock` ä¹å±äº AQS 忥å¨)å `Condition` çã
`CyclicBarrier` çåé¢æææ¯å¯å¾ªç¯ä½¿ç¨ï¼Cyclicï¼çå±éï¼Barrierï¼ãå®è¦åçäºæ
æ¯ï¼è®©ä¸ç»çº¿ç¨å°è¾¾ä¸ä¸ªå±éï¼ä¹å¯ä»¥å«åæ¥ç¹ï¼æ¶è¢«é»å¡ï¼ç´å°æåä¸ä¸ªçº¿ç¨å°è¾¾å±éæ¶ï¼å±éæä¼å¼é¨ï¼ææè¢«å±éæ¦æªççº¿ç¨æä¼ç»§ç»å¹²æ´»ã
### CyclicBarrier çåçæ¯ä»ä¹ï¼
`CyclicBarrier` å
é¨éè¿ä¸ä¸ª `count` åéä½ä¸ºè®¡æ°å¨ï¼`count` çåå§å¼ä¸º `parties` 屿§çåå§åå¼ï¼æ¯å½ä¸ä¸ªçº¿ç¨å°äºæ
æ è¿éäºï¼é£ä¹å°±å°è®¡æ°å¨å 1ã妿 count å¼ä¸º 0 äºï¼è¡¨ç¤ºè¿æ¯è¿ä¸ä»£æåä¸ä¸ªçº¿ç¨å°è¾¾æ
æ ï¼å°±å°è¯æ§è¡æä»¬æé æ¹æ³ä¸è¾å
¥çä»»å¡ã
```java
//æ¯æ¬¡æ¦æªççº¿ç¨æ°
private final int parties;
//计æ°å¨
private int count;
```
ä¸é¢æä»¬ç»åæºç æ¥ç®åççã
1ã`CyclicBarrier` é»è®¤çæé æ¹æ³æ¯ `CyclicBarrier(int parties)`ï¼å
¶åæ°è¡¨ç¤ºå±éæ¦æªççº¿ç¨æ°éï¼æ¯ä¸ªçº¿ç¨è°ç¨ `await()` æ¹æ³åè¯ `CyclicBarrier` æå·²ç»å°è¾¾äºå±éï¼ç¶åå½å线ç¨è¢«é»å¡ã
```java
public CyclicBarrier(int parties) {
this(parties, null);
}
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
```
å
¶ä¸ï¼`parties` å°±ä»£è¡¨äºææ¦æªç线ç¨çæ°éï¼å½æ¦æªççº¿ç¨æ°éè¾¾å°è¿ä¸ªå¼çæ¶åå°±æå¼æ
æ ï¼è®©ææçº¿ç¨éè¿ã
2ãå½è°ç¨ `CyclicBarrier` 对象è°ç¨ `await()` æ¹æ³æ¶ï¼å®é
ä¸è°ç¨çæ¯ `dowait(false, 0L)`æ¹æ³ã `await()` æ¹æ³å°±åæ ç«èµ·ä¸ä¸ªæ
æ çè¡ä¸ºä¸æ ·ï¼å°çº¿ç¨æ¡ä½äºï¼å½æ¦ä½ççº¿ç¨æ°éè¾¾å° `parties` ç弿¶ï¼æ
æ æä¼æå¼ï¼çº¿ç¨æå¾ä»¥éè¿æ§è¡ã
```java
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
```
`dowait(false, 0L)`æ¹æ³æºç åæå¦ä¸ï¼
```java
// å½çº¿ç¨æ°éæè
è¯·æ±æ°éè¾¾å° count æ¶ await ä¹åçæ¹æ³æä¼è¢«æ§è¡ãä¸é¢ç示ä¾ä¸ count çå¼å°±ä¸º 5ã
private int count;
/**
* Main barrier code, covering the various policies.
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
// éä½
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
// å¦æçº¿ç¨ä¸æäºï¼æåºå¼å¸¸
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
// coutå1
int index = --count;
// å½ count æ°éå为 0 ä¹å说ææåä¸ä¸ªçº¿ç¨å·²ç»å°è¾¾æ
æ äºï¼ä¹å°±æ¯è¾¾å°äºå¯ä»¥æ§è¡await æ¹æ³ä¹åçæ¡ä»¶
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// å° count é置为 parties 屿§çåå§åå¼
// å¤éä¹åçå¾
ç线ç¨
// ä¸ä¸æ³¢æ§è¡å¼å§
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
```
## èæçº¿ç¨
èæçº¿ç¨å¨ Java 21 æ£å¼åå¸ï¼è¿æ¯ä¸é¡¹ééçº§çæ´æ°ãè½ç¶ç®åé¢è¯ä¸é®çä¸å¤ï¼ä½è¿æ¯å»ºè®®å¤§å®¶å»ç®åäºè§£ä¸ä¸ãæåäºä¸ç¯æç« æ¥æ»ç»èæçº¿ç¨å¸¸è§çé®é¢ï¼[èæçº¿ç¨å¸¸è§é®é¢æ»ç»](https://javaguide.cn/java/concurrent/virtual-thread.html)ï¼å
å«ä¸é¢è¿äºé®é¢ï¼
1. ä»ä¹æ¯èæçº¿ç¨ï¼
2. èæçº¿ç¨åå¹³å°çº¿ç¨æä»ä¹å
³ç³»ï¼
3. èæçº¿ç¨æä»ä¹ä¼ç¹å缺ç¹ï¼
4. å¦ä½å建èæçº¿ç¨ï¼
5. èæçº¿ç¨çåºå±åçæ¯ä»ä¹ï¼