[TOC]
<br/>
> ### `wait/notify`
* 等待/通知的相關方法是任意Java對象都具備的,因為這些方法被定義在所有對象的超類`java.lang.Object`上。

* 使用`wait()`、`notify()`和`notifyAll()`時需要先對調用對象加鎖。
* 調用`wait()`方法后,線程狀態由`RUNNING`變為`WAITING`,并將當前線程放置到對象的等待隊列。
* `notify()`或`notifyAll()`方法調用后,等待線程依舊不會從`wait()`返回,需要調用`notify()`或`notifAll()`的線程釋放鎖之后,等待線程才有機會從`wait()`返回。
* `notify()`方法將等待隊列中的一個等待線程從等待隊列中移到同步隊列中,而`notifyAll()`方法則是將等待隊列中所有的線程全部移到同步隊列,被移動的線程狀態由`WAITING`變為`BLOCKED`。
* 從`wait()`方法返回的前提是獲得了調用對象的鎖。
<br/>
> ### `sleep`和`wait`的區別
* `sleep`是`Thread`類的方法,`wait`是`Object`類中定義的方法
* `Thread.sleep`不會導致鎖行為的改變,如果當前線程是擁有鎖的,那么`Thread.sleep`不會讓線程釋放鎖。和鎖相關的方法都定義在`Object`類中,因此調用`Thread.sleep`是不會影響鎖的相關行為。
* `wait`必須在`synchronized`塊中。`wait`執行時會釋放對象鎖,通過使用`notify`或者`notifyAll`來喚醒
<br/>
> ### 等待/通知的經典范式
* 等待方遵循如下原則
* 1)獲取對象的鎖。
* 2)如果條件不滿足,那么調用對象的wait()方法,被通知后仍要檢查條件。
* 3)條件滿足則執行對應的邏輯。
```
synchronized(對象) {
while(條件不滿足) {
對象.wait();
}
對應的處理邏輯
}
```
* 通知方遵循如下原則
* 1)獲得對象的鎖。
* 2)改變條件。
* 3)通知所有等待在對象上的線程。
```
synchronized(對象) {
改變條件對象.notifyAll();
}
```
<br/>
> ### 兩個線程交替輸出奇偶數到100`synchronized` `wait/notify`
```
public class Demo1 {
//兩線程共享的變量
static int i = 1;
public static class ThreadDemo implements Runnable{
Object lock;
public ThreadDemo(Object lock) {
this.lock = lock;
}
public void run() {
synchronized(lock){
while(i <= 100){
System.out.println(Thread.currentThread().getName() + ":" + i);
i++;
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
Object lock = new Object();
Thread t1 = new Thread(new ThreadDemo(lock), "thread1");
Thread t2 = new Thread(new ThreadDemo(lock), "thread2");
t1.start();
t2.start();
}
}
```
<br/>
> ### 三個線程交替輸出數字到100`synchronized` `wait/notify`
```
public class Demo2{
static int i = 1;
static class ThreadDemo implements Runnable{
Object lock;
int t;
public ThreadDemo(Object lock, int t){
this.lock = lock;
this.t = t;
}
public void run(){
synchronized(lock){
while(i <= 100){
if(i % 3 == t){
System.out.println(Thread.currentThread().getName() + ":" + i);
i++;
lock.notifyAll();
}else{
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public static void main(String[] args) {
Object lock = new Object();
for(int i = 0; i < 3; i++){
Thread t = new Thread(new ThreadDemo(lock, i), "thread" + (i + 1));
t.start();
}
}
}
```
- asD
- Java
- Java基礎
- Java編譯器
- 反射
- collection
- IO
- JDK
- HashMap
- ConcurrentHashMap
- LinkedHashMap
- TreeMap
- 阻塞隊列
- java語法
- String.format()
- JVM
- JVM內存、對象、類
- JVM GC
- JVM監控
- 多線程
- 基礎概念
- volatile
- synchronized
- wait_notify
- join
- lock
- ThreadLocal
- AQS
- 線程池
- Spring
- IOC
- 特性介紹
- getBean()
- creatBean()
- createBeanInstance()
- populateBean()
- AOP
- 基本概念
- Spring處理請求的過程
- 注解
- 微服務
- 服務注冊與發現
- etcd
- zk
- 大數據
- Java_spark
- 基礎知識
- Thrift
- hdfs
- 計算機網絡
- OSI七層模型
- HTTP
- SSL
- 數據庫
- Redis
- mysql
- mybatis
- sql
- 容器
- docker
- k8s
- nginx
- tomcat
- 數據結構/算法
- 排序算法
- 快排
- 插入排序
- 歸并排序
- 堆排序
- 計算時間復雜度
- leetcode
- LRU緩存
- B/B+ 樹
- 跳躍表
- 設計模式
- 單例模式
- 裝飾者模式
- 工廠模式
- 運維
- git
- 前端
- thymeleaf
- 其他
- 代碼規范
- work_project
- Interview