本文已参与[新人创作礼]活动,一起开启掘金创作之路.
- 什么是“生产者和消费者模式”? 生产线程负责生产,消费线程负责消费。 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方法。
- wait和notify方法不是线程对象的方法,是普通java对象都有的方法。
- wait方法和notify方法建立在线程同步的基础之上。因为多线程要同时操作一个仓库。有线程安全问题。
- wait方法作用: o.wait()让正在o对象上活动的线程t进入等待状态,并且释放掉t线程之前占有的o对象的锁。
- notify方法作用: o.notify()让正在o对象上等待的线程唤醒,只是通知,不会释放o对象上之前占有的锁。
- 模拟这祥一个需求: 仓库我们采用List集合。 List集合中假设只能存储1个元素。1个元素就表示仓库满了。 如果List集合中元素个数是0,就表示仓厍空了。 必须做到这种效果:生产1个消费1个。
实现
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List list = new ArrayList();
Thread t1 = new Procuder(list);
Thread t2 = new Consumer(list);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
}
}
// 生产者类
class Procuder extends Thread {
private List list;
public Procuder(List list) {
this.list = list;
}
@Override
public void run() {
// 死循环,表示一直生产
while (true) {
// 给仓库对象加锁
synchronized (list) {
// 大于0,说明仓库中已经有1一个元素了
if (list.size() > 0) {
try {
// 让当前线程进入等待状态,并释放Producer之前占有的list对象的锁,使得下面的Consumer可以获得list的锁继续执行
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 程序能执行到这里,说明仓库是空的,应该生产一个商品
Object obj = new Object();
list.add(obj);
System.out.println(Thread.currentThread().getName() + "生产" + obj);
// 唤醒调用了list的wait方法的线程,注意当前有synchronized限制,所以消费者需要等到生产者出了synchronized代码块后才会执行
list.notifyAll();
}
}
}
}
// 消费者类类
class Consumer extends Thread {
private List list;
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
// 死循环,表示一直消费
while (true) {
// 给仓库对象加锁
synchronized (list) {
// 等于0,说明仓库中没有元素可以消费
if (list.size() == 0) {
try {
// 让当前线程进入等待状态,并释放Consumer之前占有的list对象的锁,使得上面的Procuder可以获得list对象的锁继续执行
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 程序能执行到这里,说明仓库是有元素的,应该消费一个商品
Object obj = list.remove(0);
System.out.println(Thread.currentThread().getName() + "消费" + obj);
// 唤醒调用了list的wait方法的线程,注意当前有synchronized限制,所以消费者需要等到生产者出了synchronized代码块后才会执行
list.notifyAll();
}
}
}
}