生产者与消费者问题研究

首先模拟单缓冲区生产者和消费者问题,wait()通常都要放入synchronized修饰的语句块中或者方法中,唤醒该线程需要调用同一对象的notify()或者notifyAll()方法

当调用某个对象notify()方法时,将从该对象等待集合中选择一个等待的线程唤醒,唤醒的线程将从等待集合中删除。

notifyAll是唤醒所有线程,只不过由于synchronized,最终只有一个线程进入

class basket{
	private boolean empty;
	private int good;
	public basket(){
		empty=true;//一开始篮子是空的
	}
	public synchronized void put(int value){//放入重量为value的内容
		while(!empty){//当篮子不为空时
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		good=value;
		System.out.println("往篮子里面放入"+good);
		empty=false;
		notify();
	}
	public synchronized void get(){//取物品
	while(empty){
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	System.out.println("从篮子里面获得"+good);
	empty=true;
	notify();
	}
}
class producer implements Runnable{
	private basket b=new basket();
	public producer(basket b){
		this.b=b;
	}
	public void run(){
	 for (int i=1;i<=10;i++)
		 b.put((int)(Math.random()*100));
	}
}
class consumer implements Runnable{
	 private basket b=new basket();
	 public consumer(basket b){
		 this.b=b;
	 }
	 public void run(){
		for (int i=1;i<=10;i++)
		 b.get();
	 }
}
public class test8 {
	public static void main(String[] args) {
		 basket b=new basket();
		 producer p=new producer(b);
		 Thread t1=new Thread(p);
		 consumer c=new consumer(b);
		 Thread t2=new Thread(c);
		 t1.start();
		 t2.start();
	}
 
 
}
对于多缓冲区需要借助循环队列来实现存储

class basket2{
	private int []a;//存储缓冲区
	private int front;//队首
	private int rear;//队尾
	public basket2(){//初始化存储区
		a=new int[10];
		front=0;
		rear=0;
	}
	public boolean isEmpty(){
		return front==rear;
	}
	public boolean isfull(){
		return (front+1)%10==rear;
	}
	public synchronized void put(int goods){//为满的时候循环等待
		while(isfull()){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
      front=(front+1)%10;
      a[front]=goods;
      System.out.println("生产者放入"+goods);
      notify();
	}
	public synchronized void get(){
		while(isEmpty()){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		rear=(rear+1)%10;
		System.out.println("消费者取出"+a[rear]);
		notify();
 	}
}
class producer2 extends Thread{
	private basket2 b=new basket2();
	public producer2(basket2 b){
		this.b=b;
	}
	public void run(){
		for (int i=1;i<=100;i++)
			b.put((int)(Math.random()*100));
	}
}
class consumer2 extends Thread{
	private basket2 b=new basket2();
	public consumer2(basket2 b){
		this.b=b;
	}
	public void run(){
		for (int i=1;i<=100;i++)
			b.get();
	}
}
public class test9 {//一个生产者和消费者共用多个缓冲区
 public static void main(String[] args) {
	basket2 b=new basket2();
	producer2 p=new producer2(b);
	consumer2 c=new consumer2(b);
	p.start();
	c.start();
	
}
}


JDK1.5之后引入条件变量:

synchronized被Lock锁替换后,对应的监视方法wait,notify,notifyAll也要用awit,signal,signalAll操作替换。

class basket2{
	private int []a;//存储缓冲区
	private int front;//队首
	private int rear;//队尾
	private Lock lock;
	private Condition full;
	private Condition empty;
	public basket2(){//初始化存储区
		a=new int[10];
		front=0;
		rear=0;
		lock=new ReentrantLock();
		empty=lock.newCondition();
		full=lock.newCondition();
	}
	public boolean isEmpty(){
		return front==rear;
	}
	public boolean isfull(){
		return (front+1)%10==rear;
	}
	public  void put(int goods){//为满的时候循环等待
		lock.lock();
		while(isfull()){
			try {
				full.await();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
      front=(front+1)%10;
      a[front]=goods;
      System.out.println("生产者放入"+goods);
      empty.signal();
      lock.unlock();
	}
	public  void get(){
		lock.lock();
		while(isEmpty()){
			try {
				empty.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		rear=(rear+1)%10;
		System.out.println("消费者取出"+a[rear]);
		full.signal();
	    lock.unlock();
 	}
}
class producer2 extends Thread{
	private basket2 b=new basket2();
	public producer2(basket2 b){
		this.b=b;
	}
	public void run(){
		for (int i=1;i<=100;i++)
			b.put((int)(Math.random()*100));
	}
}
class consumer2 extends Thread{
	private basket2 b=new basket2();
	public consumer2(basket2 b){
		this.b=b;
	}
	public void run(){
		for (int i=1;i<=100;i++)
			b.get();
	}
}
public class test9 {//一个生产者和消费者共用多个缓冲区
 public static void main(String[] args) {
	basket2 b=new basket2();
	producer2 p=new producer2(b);
	consumer2 c=new consumer2(b);
	p.start();
	c.start();
}
}


java并发库中有一些线程安全的集合,比如可以使用ConcurrentLinkedDeque()来解决多缓冲区的生产者和消费者问题。

class basket3{
  private ConcurrentLinkedDeque<Integer>list=new ConcurrentLinkedDeque<Integer>();
  public void put(int n){
	  list.add(n);
	  System.out.println("向列表中装入"+n);
  }
  public void get(){
	  while(!list.isEmpty())
	  System.out.println("从列表中移除"+list.pollFirst());
  }
}
class Producer2 implements Runnable{
	basket3 b=new basket3();
	public Producer2(basket3 b){
		this.b=b;
	}
	public void run(){
		for (int i=1;i<=10;i++)
		b.put((int)(Math.random()*100));
	}
}
class Consumer2 implements Runnable{
	basket3 b=new basket3();
	private Thread t;
	public Consumer2(basket3 b,Thread t1){
		this.b=b;
		t=t1;
	}
	public void run(){
		try {
			t.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for (int i=1;i<=10;i++)
			b.get();
	}
}
  public class test10 {
	  public static void main(String[] args) {
		basket3 b=new basket3();
		Thread t1=new Thread(new Producer2(b));
		Thread t2=new Thread(new Consumer2(b,t1));
		t1.start();
		t2.start();
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值