java个人学习笔记19(多生产者多消费者+循环判断标记+notifyAll()+Lock+Condition)

1.多生产者多消费者

/**
多生产者多消费者问题
	pro1:连续生产,重复消费
	Rea:被唤醒的线程没有再判断flag标记,就直接生产或消费了。
	sol:被唤醒的线程必须再次判断flag标记,while(flag)代替if(flag)

	pro2:有可能产生死锁
	Rea:唤醒的不确定,有可能生产者线程唤醒了生产者线程
	sol:使用notifyAll()
*/

//共享资源
class Res
{
	private String name;
	private int num = 1;
	//定义flag标记,为true表示存在一个未被消费的资源,为false表示资源已被消费。
	private boolean flag;
	//生产资源
	public synchronized void setRes(String name){
		//判断标记,存在未被消费的资源则进程等待
		//使被唤醒的线程再次判断flag标记
		while(flag)
			try{this.wait();}catch(InterruptedException e){}
		this.name = name+"..."+num;
		num++;
		System.out.println(Thread.currentThread().getName()+"...Producer..."+this.name);
		//修改flag标记
		flag = true;
		//唤醒消费者
		this.notifyAll();
	}

	//消费资源
	public synchronized void getRes(){
		//判断标记,资源已被消费则进程等待
		//使被唤醒的线程再次判断flag标记
		while(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(Thread.currentThread().getName()+"...Customer..."+name);
		//修改标记
		flag = false;
		//唤醒生产者
		this.notifyAll();
	}
}

//生产者
class Pro implements Runnable
{
	private Res r;
	Pro(Res r){
		this.r = r;
	}
	public void run(){
		while(true)
			r.setRes("phone");
	}
}

//消费者
class Cus implements Runnable
{
	private Res r;
	Cus(Res r){
		this.r = r;
	}
	public void run(){
		while(true)
			r.getRes();
	}
}

class ProducerCustomerDemo1
{
	public static void main(String[] args) 
	{
		//创建一个资源
		Res r = new Res();
		//创建两个任务
		Pro p = new Pro(r);
		Cus c = new Cus(r);
		//创建两个生产者线程和两个消费者线程
		Thread t1 = new Thread(p);
		Thread t2 = new Thread(p);
		Thread t3 = new Thread(c);
		Thread t4 = new Thread(c);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
pro1:



pro2:


效率有点低!

2.Lock和Condition接口实现高效多生产者多消费者

查阅API(jdk1.5以上)java.util.concurrent.lock 
lock接口:按照面向对象的思想,将锁单独封装成一个对象,
 并提供对锁的显示操作 lock():获取锁  unlock():释放锁
 是同步的替代


condition接口:是Object中的监视器方法的替代
await()  signal()  signalAll()
之前是将监视器方法封装到每一个对象中,现在是将监视器方法只封装到condition对象中


condition对象与lock对象的绑定
通过lock接口的newCondition()方法完成

/**
解决效率低下的问题:
一锁绑定两组监视器,一组监视生产者进程,另一组监视消费者进程

*/
import java.util.concurrent.locks.*;
//共享资源
class Res
{
	private String name;
	private int num = 1;
	//定义flag标记,为true表示存在一个未被消费的资源,为false表示资源已被消费。
	private boolean flag;
	//创建Lock对象,通过已经实现的类ReentrantLock
	private Lock l = new ReentrantLock();
	//创建监视器对象,并将监视器对象与锁对象绑定
	//生产者监视器
	private Condition c_Pro = l.newCondition();
	//消费者监视器
	private Condition c_Cus = l.newCondition();
	//生产资源
	public void setRes(String name){
		//获取锁
		l.lock();
		try{
			//判断标记,存在未被消费的资源则进程等待
			while(flag)
				try{c_Pro.await();}catch(InterruptedException e){}
			this.name = name+"..."+num;
			num++;
			System.out.println(Thread.currentThread().getName()+"...Producer..."+this.name);
			//修改flag标记
			flag = true;
			//唤醒消费者
			c_Cus.signal();
		}finally{
			//释放锁
			l.unlock();
		}
		
	}

	//消费资源
	public void getRes(){
		//获取锁
		l.lock();
		try{
			//判断标记,资源已被消费则进程等待
			while(!flag)
				try{c_Cus.await();}catch(InterruptedException e){}
			System.out.println(Thread.currentThread().getName()+"...Customer..."+name);
			//修改标记
			flag = false;
			//唤醒生产者
			c_Pro.signal();
		}finally{
			//释放锁
			l.unlock();
		}
	}
}

//生产者
class Pro implements Runnable
{
	private Res r;
	Pro(Res r){
		this.r = r;
	}
	public void run(){
		while(true)
			r.setRes("phone");
	}
}

//消费者
class Cus implements Runnable
{
	private Res r;
	Cus(Res r){
		this.r = r;
	}
	public void run(){
		while(true)
			r.getRes();
	}
}

class NewProducerCustomerDemo
{
	public static void main(String[] args) 
	{
		//创建一个资源
		Res r = new Res();
		//创建两个任务
		Pro p = new Pro(r);
		Cus c = new Cus(r);
		//创建两个生产者线程和两个消费者线程
		Thread t1 = new Thread(p);
		Thread t2 = new Thread(p);
		Thread t3 = new Thread(c);
		Thread t4 = new Thread(c);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值