生产者与消费者

线程间的通讯–生产者与消费者问题

1.1模式原理

它描述的是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者可以从仓库中取走产品,解决生产者/消费者问题,我们需要采用某种机制保护生产者和消费者之间的同步;
同步问题核心在于:如何保证同一资源被多个线程并发访问时的完整性,常用的方法就是加锁,保证资源在任意时刻只被一个线程访问;

2.1实现

采用wait()、notify()和notifyAll()方法
wait():当缓冲区已满或空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行
		·是Object的方法
		·调用方式:对象.wait();
		·表示释放 对象 这个锁标记,然后在锁外边等待(对比sleep(),sleep是抱着锁休眠的)
		·等待,必须放到同步代码段中执行	
notify():当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态
		·是Object的方法
		·调用方式:对象.notify();
		·表示唤醒 对象 所标记外边在等待的一个线程
notifyAll():全部唤醒
		·是Object的方法
		·调用方式:对象.notifyAll()
		·表示唤醒  对象 所标记外边等待的所有线程

模拟生产面包和消费面包,实现代码:

/*
*面包
*/
public class Bread {
	private int id;
	private String productName;
    
	public Bread() {}
	
	public Bread(int id, String productName) {
		super();
		this.id = id;
		this.productName = productName;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}

	@Override
	public String toString() {
		return "Bread [id=" + id + ", productName=" + productName + "]";
	}
	
	
}
/*
 * 面包容器
 */
public class BreadCon {
	private Bread con;
	private boolean flag; //
	
	//放入面包
	public synchronized void input(Bread b){
		while(flag==true){//使用while循环,保证线程在被唤醒后,需要再次判断条件.
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
	this.con=b;
	System.out.println(Thread.currentThread().getName()+"生产了"+b.getId());
	flag=true;//更改锁标记
	this.notifyAll();//避免死锁问题但此方法只有一个等待队列,每次唤醒所以线程,效率低;
	}
	
	//吃面包
	public synchronized void output(){
		while(flag==false){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	Bread b=con;//取出面包
	con=null;//取出面包后仓库就没有这个已经取出的面包了
	System.out.println(Thread.currentThread().getName()+"消费了"+b.getId()+" 生产者:"+b.getProductName());
	flag=false;
	this.notifyAll();
	}
}
/*
 * 生产面包类
 */
public class Product implements Runnable{
	private BreadCon con;
	public Product(BreadCon con) {
		this.con=con;
	}
	@Override
	public void run() {
		for(int i=1;i<=30;i++){
			Bread b=new Bread(i, Thread.currentThread().getName());
			this.con.input(b);
		}
	}
}
/*
 * 消费面包
 */
public class Consume implements Runnable{
	private BreadCon con;
	public Consume(BreadCon con) {
		this.con=con;
	}
	@Override
	public void run() {
		for(int i=1;i<=30;i++){
			con.output();
		}
	}
}
public static void main(String[] args) {
		//1创建容器
		BreadCon con=new BreadCon();
		//2生产
		Product product=new Product(con);
		//3消费
		Consume consume=new Consume(con);
		//4线程对象
		Thread shaqiang=new Thread(product, "莎强");
		Thread xiaocang=new Thread(consume,"小苍");
		//5启动
		shaqiang.start();
		xiaocang.start();
	}
//使用Jdk1.5 Lock优化生产者和消费者
package com.qf.day20_11;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;



/**
 * 面包容器
 * @author wgy
 *
 */
public class BreadCon {
	private Bread con;
	private boolean flag;
	private Lock lock=new ReentrantLock();
	
	Condition proCondition=lock.newCondition();
	Condition conCondition=lock.newCondition();
	
	/**
	 * 放入面包
	 */
	public  void input(Bread b) {
		lock.lock();
		try {
			while (flag) {
				try {
					proCondition.await();
				} catch (Exception e) {
					// TODO: handle exception
				}

			}
			con = b;
			System.out.println(Thread.currentThread().getName() + "生产了" + b.getId() + "面包");
			flag = true;
			conCondition.signal();
		} finally {
			lock.unlock();
		} 
		
		
	}
	/**
	 * 消费面包
	 */
	public  void output() {
		lock.lock();
		try {
			while (!flag) {
				try {
					conCondition.await();
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
			Bread b = con;
			System.out
					.println(Thread.currentThread().getName() + "消费了" + b.getId() + "面包, 生产者名字:" + b.getProductName());
			con = null;
			flag = false;
			proCondition.signal();
		} finally {
			lock.unlock();
		}
	}
	
}	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值