您的位置:首页 > 编程语言 > Java开发

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

2014-05-09 17:01 731 查看
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐