经典案例:生产者和消费者
程序员文章站
2022-05-05 16:41:50
...
经典案例:生产者和消费者
一、什么是生产者和消费者?
生产者与消费者问题是多线程同步的一个经典问题。生产者和消费者同时使用一块缓冲区,生产者生产商品放入缓冲区,消费者从缓冲区中取出商品。我们需要保证的是,当缓冲区满时,生产者不可生产商品;当缓冲区为空时,消费者不可取出商品。
二、如何解决一个生产者与消费者问题
主要三种解决方式:
-
wait()与notify()方法
-
Lock与Condition机制
-
BlockingQueue阻塞队列
1.wait()与notify()方法
wait()方法使用条件:
wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
- 当生产产品数量满时,调用wait()方法,使得生产者释放锁,当前线程阻塞,消费者线程可以获得锁。
- 当产品数量为空时,调用wait()方法,使得消费者释放锁,当前线程阻塞,生产者线程可以获得锁。
notify()方法使用条件:
notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
- 如果刚执行的是消费者,那么产品数量为0,就执行wait()方法等待。那么在执行生产者时,只要生产一个产品就会通过notify()方法唤醒消费者,让消费者来消费产品。
- 如果生产者生产产品过快,消费者来不及消费,并且到达产品上限。那么生产者就执行wait()方法等待。在消费者消费一个产品就会通过notify()方法唤醒生产者,让生产者生产产品。
代码如下:
//调度类
public class Clerk {
//共享资源 产品数量
private static int productCount = 0;
//生产产品
//必须加上同步方法,不然两个线程会产生线程安全问题
public synchronized void produceProduct(){
if (productCount < 20){
productCount++;
System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品");
//唤醒等待的消费者
notify();
}else {
//等待
try {
//产品数量满了,进入等待
wait();
System.out.println("生产满了奥,我要休息一下");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumeProduct(){
if (productCount > 0){
System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品");
productCount--;
//唤醒等待的生产者
notify();
}else {
try {
//产品数量为空,进入等待
wait();
System.out.println("商品没了奥,我要休息一下");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//生产者
public class Producer extends Thread {
private Clerk clerk;
public Producer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始生产产品.....");
while (true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
//消费者
public class Consumer extends Thread {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始消费产品.....");
while (true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}
//测试类 模拟两个生产者,两个消费者
public class Test {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
p1.setName("生产者1");
Producer p2 = new Producer(clerk);
p2.setName("生产者2");
Consumer c1 = new Consumer(clerk);
c1.setName("消费者1");
Consumer c2 = new Consumer(clerk);
c2.setName("消费者2");
p1.start();
p2.start();
c1.start();
c2.start();
}
}
运行结果如下:
上一篇: 生产者消费者案例