package com.me.threadtest;
/**
* 多线程之生产者与消费者模式:即生产一个,消费一个
*/
public class ProducerAndConsumer {
public static void main(String[] args) {
/**
* 1、当只创建两个线程时是没什么问题,符合生产者与消费者模式;
*
* 2、但是在实际工作开发中,可不止两个线程,即有多个生产者线程,
* 有多个消费者线程,这样产生的问题是:
* 生产者与消费者不同步:即生产了多个商品,但是只消费了一个商品;
* 或者生产一个商品却消费多次。
*
* 问题原因:生产线程1在生产完商品后,把本方的生产线程2唤醒了,
* 之后线程1就等待,然后线程2就执行生产而没有判断 if(flag)
* 里面的flag标记状态,线程2是在wait()处醒来后直接往下执行了,
* 因为if(flag)只执行一次。
*
* 3、 那怎么保证多个线程之间如何生产与消费同步呢?
* 即生产一个,消费一个,不能多生产,也不能多消费!
*
* 解决方案:把if(flag)条件判断改为 while(flag)循环,
* 这样线程2在wait()醒来之后就会继续判断flag状态,
* flag=true, 线程2就会等待,不会再次生产商品。
*
* 同理: 消费方法中的 if(!flag)改为while(!flag),
* 消费线程3在消费完后唤醒消费线程4,然后线程3等待状态,
* 线程4在wait()醒来后继续判断flag状态,flag=false,
* 则线程 4也处于等待,不再消费。
*
* 但是该方案会产生问题:生产线程1生产后唤醒线程2,然后处于等待状态,
* 线程2判读后有商品也处于等待状态;
* 线程3消费商品后唤醒线程4,然后处于等待状态,
* 线程4判断无商品后也处于等待状态。
* 这样就会造成所有线程处于等待状态:即所有线程都处于等待状态,
* 生产者线程等待消费者线程消费,而消费者线程就会等待
* 生产者线程进行生产。
*
* 4、那怎么解决所有线程都处于等待的问题?
* 分析:之所以全部线程都处于等待,是因为生产线程
* 或消费线程可能会把本方的线程给唤醒,而没有把对方的线程给唤醒。
*
* 解决方案:线程在调用notify()方法改为调用 notifyAll()方法,
* 这样就会把在线程池中所有等待的线程都唤醒,
* 即使是自己本方的线程被唤醒了也会判断flag而处于等待状态。
*
*/
Goods goods = new Goods();
//创建两个线程对象
Thread t1 = new Thread(new Producer(goods));
Thread t2 = new Thread(new Consumer(goods));
Thread t3 = new Thread(new Producer(goods));
Thread t4 = new Thread(new Consumer(goods));
//启动两个线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Goods {
private String name; //商品名
private int count = 1; //商品编号,初始值为 1
private boolean flag = false; //控制标记,默认false
//同步方法中的默认监视器(锁)是当前对象的引用this,
//同步静态方法中的默认锁是当前所在类的字节码文件对象:类名.class
//生产商品
public synchronized void set(String name) {
/*if (flag) {
}*/
while (flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + "---" + count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
flag = true;
// this.notify();
this.notifyAll();
}
//消费商品
public synchronized void out() {
/*if (!flag) {
}*/
while (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out .println(Thread.currentThread().getName() + ".....消费者..." + this.name);
flag = false;
// this.notify();
this.notifyAll();
}
}
//生产者
class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true) {
goods.set("脑残酸菜牛肉面");
}
}
}
//消费者
class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true) {
goods.out();
}
}
}
多线程之生产者与消费者模式
最新推荐文章于 2022-04-27 09:50:27 发布