生产者和消费者模式概述
生产者消费者模式是一个十分经典的多线程协作的模式。
生产者消费者问题,主要包含了两类线程:
1.生产者线程用于生产数据
2.消费者线程用于获取数据
为了解耦生产者和消费者之间的关系,通常会采用共享的数据区域,就像一个仓库
生产者生产数据之后放到共享数据区域,并不需要关心消费者的行为;
消费者只需要从共享数据中获取数据,并不用关系生产者的行为。
生产者和消费者中的等待唤醒
当生产者线程在共享数据区域生产数据之后,需要去唤醒等待中的消费者线程获取数据。
当消费者线程在共享数据区域获取数据之后,需要唤醒等待中的消费者线程去生产数据。
方法名 | 说明 |
---|---|
void wait() | 导致当前线程等待,知道另一个线程调用对象的notify()或notifyAll() |
void notify() | 唤醒正在等待对象监视器的单个线程 |
void notifyAll() | 唤醒正在等待对象监视器的所有线程 |
public class TestDemo {
public static void main(String[] args) {
Box b = new Box();
Producer producer = new Producer(b);
Customer customer = new Customer(b);
Thread p = new Thread(producer);
Thread c = new Thread(customer);
p.start();
c.start();
}
}
class Box {//牛奶箱
private int milk;
private boolean flag = false;
public synchronized void put(int milk) {
if(flag){//当牛奶箱中有牛奶时等待被唤醒
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//牛奶箱中没有牛奶时生产牛奶
this.milk = milk;
System.out.println("放入第" + this.milk + "瓶牛奶");
flag = true;
notifyAll();//唤醒消费者获取牛奶
}
public synchronized void get() {
if(!flag){//牛奶箱中没有牛奶时等待被唤醒
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//牛奶箱中有牛奶时获取牛奶
System.out.println("获取第" + milk + "瓶牛奶");
flag = false;
notifyAll();//唤醒生产者生产牛奶
}
}
class Producer implements Runnable {//生产者
private Box b;
public Producer() {
}
public Producer(Box b) {
this.b = b;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
b.put(i);
}
}
}
class Customer implements Runnable{//消费者
private Box b;
public Customer(){
}
public Customer(Box b){
this.b = b;
}
@Override
public void run(){
while(true){
b.get();
}
}
}