[TOC]
<br/>
> ### `wait/notify`
* 等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类`java.lang.Object`上。
![](https://i.loli.net/2019/03/10/5c851dd4b9ff0.png)
* 使用`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