wait()
、notify()
和notifyAll()
方法是 Object 的三个方法。
wait()
使当前线程进入等待状态,直到:
- 其它线程调用
notify()
方法或者notifyAll()
方法 - 其它线程中断了当前线程
- 到了指定的 wait 时间
它的使用方式是在一个循环中
synchronized (obj) {
// 条件不满足
while (condition does not hold) {
obj.wait();
}
// 执行满足条件的代码
}
调用wait()
当前线程会释放锁,让出CPU进入等待状态。notify()
和notifyAll()
都是唤醒当前正在等待的线程。而notify()
只唤醒其中一个线程,唤醒的线程是随机的,notifyAll()
方法则是唤醒所有正在等待的线程。线程被唤醒后并不会马上执行任务,由哪个线程去执行任务是由系统调度。wait()
、notify()
、notifyAll()
需要被包括在syncronized
代码块或者方法中。
使用wait()
、notify()
、notifyAll()
实现一个消费者与生产者模式。
消费者与生产者有一个共同的容器,消费者从容器中取出数据消费,生产者生产数据后放入容器。当容器为空时消费者阻塞,同时生产者生产数据;当容器满时,生产者堵塞不再生产,通知消费者消费。
容器
public class Container {
private static final int MAX_SIZE = 5;
private final LinkedList<Object> list = new LinkedList<>();
// 生产
public void product() {
synchronized (list) {
while (list.size() >= MAX_SIZE) { // 容器里面的数据达到了最大,生产者就进入等待状态
try {
System.out.println("容器装满了,有" + list.size() + "条数据 --" + Thread.currentThread().getName());
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.addFirst(new Object());
System.out.println("+++++生产者生产了一条数据,有" + list.size() + "条数据 --" + Thread.currentThread().getName());
list.notifyAll();
}
}
public void consume() {
synchronized (list) {
while (list.size() <= 0) { // 容器里面数据为空,消费者就进入等待状态
try {
System.out.println("容器没有数据了 --" + Thread.currentThread().getName());
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.removeLast();
System.out.println("-----消费者消费了一条数据,有" + list.size() + "条数据 --" + Thread.currentThread().getName());
list.notifyAll();
}
}
}
生产者
public class Producer implements Runnable{
private final Container mContainer;
public Producer(Container container) {
mContainer = container;
}
@Override
public void run() {
mContainer.product();
}
}
消费者
public class Consumer implements Runnable {
private final Container mContainer;
public Consumer(Container container) {
mContainer = container;
}
@Override
public void run() {
mContainer.consume();
}
}
public static void main(String[] args) {
Container container = new Container();
for (int i = 0; i < 8; i++) {
Producer producer = new Producer(container);
Thread thread = new Thread(producer);
thread.setName("生产者线程" + i);
thread.start();
}
for (int i = 0; i < 8; i++) {
Consumer consumer = new Consumer(container);
Thread thread = new Thread(consumer);
thread.setName("消费者线程" + i);
thread.start();
}
}
image
在
Container
类中的synchronized
持有的是list
对象锁,那么wait()
、notify()
、notifyAll()
方法都必须调用list
的方法。当然synchrozied
也可以持有this
,表示当前Container
对象锁,或者synchronized
修饰在方法上,那么wait()
、notify()
、notifyAll()
方法都必须调用Container
对象的方法,即this.wait()
或者wait()
。
后续文章会有专门关于synchronized
的讲解。
网友评论