多线程之生产者与消费者模式


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();
		}
	}
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值