🍇一、提出两个问题
🥄什么是wait/notify
机制?
🥢wait/notify
机制用来干什么的?
🍈二、尝试回答
🥒什么是wait/notify机制
首先wait
和notify
都是Object
类里面的native
方法,为什么叫做wait/notify
机制,是因为这两使用的时候都是一起用的。
🥦wait/notify机制用来干什么
一般我们说到wait/notify
机制都是说用来实现线程之间的通信。
🍓三、介绍一下wait/notify
wait
和notify
都是Object
类里面的方法
wait
是用来阻塞当前线程,线程调用wait
方法后会被阻塞并释放线程持有的锁
notify
使用来唤醒阻塞的线程,线程调用notify
方法后并不会立马释放锁,只有执行完同步方法后才会释放锁。
除了wait
和notify
,还有对应的wait(timeout)
和notifyAll
,wait(timeout)
是阻塞多少时间,notifyAll
是唤醒所有阻塞线程。
public final void wait() throws InterruptedException {
wait(0);
}
public final native void notify();
🍊四、提出一个问题
😔问题:wait和notify用来阻塞线程的,为什么在Object类,而不在Thread类里面?
要回答这个问题就要从wait
和notify
的底层实现原理说起了,首先wait
和notify
都是native
的,是通过c
来实现的,
每一个对象都会生成一个objectMonitor
类对应,当调用Java
对象的wait
和notify
方法,其实就是调用objectMonitor
的wait
和notify
方法。
所以虽然wait
和notify
都是来操作线程的,但是是通过对象关联类objectMonitor
来实现的,所以wait
和notify
都在Object
类里面。
🍒五、工作流程
这里我们来梳理一下wait
和notify
工作的流程,关于wait
和notfiy
的源码可以参考
1.当有两个线程来获取锁,同时在等待队列里面竞争锁。
2.现在线程t1
获取到了锁。
3.现在t1
获取到了锁,在执行同步代码的过程中调用了锁对象的wait
方法,线程t1
就将被阻塞。
4.线程t1
被放到阻塞队列并且释放锁,线程t1
将编程阻塞状态。
5.线程t2
获取到了锁,然后执行同步代码。
6.线程t2
在执行同步代码的过程中调用了notify
方法,会唤醒处于阻塞状态的t1
,线程t2
执行完同步代码之后才会释放锁。
7.线程t1
被唤醒后重新回到等待队列、线程t2
执行完同步代码之后也会回到等待队列,进行下一轮的锁竞争。
🍎六、总结
回到最开始哪个问题,wait/notify
机制是来干什么的
wait/notify
机制是用来通信的,并不是完全贴切,wait/notify
机制并不是说线程之间直接交流的,而是用来操作线程的,通过阻塞线程和唤醒阻塞线程来切换锁的占用,线程之间没有直接的交流。
🥝七、生产者消费者模式
最后用wait/notify
实现一个生产者消费者代码
😩生产者
public class Producer extends Thread {
private List<Object> objects;
private int length;
public Producer(List<Object> objects, int length) {
this.objects = objects;
this.length = length;
}
@Override
public void run() {
try {
while (true) {
synchronized (objects) {
if (objects.size() >= length) {
objects.notifyAll();
objects.wait();
} else {
Object object = new Object();
objects.add(object);
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "生产了一个商品,库存:" + objects.size());
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
😃消费者
public class Consumer extends Thread {
private List<Object> objects;
public Consumer(List<Object> objects) {
this.objects = objects;
}
@Override
public void run() {
try {
while (true) {
synchronized (objects) {
if (objects.size() == 0) {
objects.notifyAll();
} else {
objects.remove(0);
System.out.println(Thread.currentThread().getName() + " 消费了一个商品,还剩:" + objects.size());
Thread.sleep(1000);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
😈管理员
public class MainDemo {
public static void main(String[] args) {
List<Object> objects = new ArrayList<>();
int length = 10;
Producer p1 = new Producer(objects,length);
p1.setName("生产者");
p1.start();
Consumer c1 = new Consumer(objects);
c1.setName("消费者");
c1.start();
}
}