黑马程序员_多线程间的通信(生产者与消费者)

来源:互联网 发布:淘宝名词解释大全 编辑:程序博客网 时间:2024/04/30 09:17

为了进一步体现线程的安全问题以及线程的等待唤醒机制。来看一个例子:

class Resource{private String name;private int count = 1;private boolean flag = false;public  void set(String name){if (flag)try{wait();}catch (Exception e){}this.name = name+"---"+count++;System.out.println(Thread.currentThread().getName()+" produces "+this.name);flag = true;this.notify();}public void out(){if (!flag)try{wait();}catch (Exception e){}System.out.println(Thread.currentThread().getName()+"    consumes "+this.name);flag = false;this.notify();}}
如果只是开启了两个线程,运行时会轮流“消费--生产”很和谐。但如果两者各开启两条线程,就会出现这样的情况。

t1取得资格、执行权->生产商品1、将flag之位true后t1进入阻塞状态、t2取得资格和执行权->进入阻塞状态,t3取得资格和执行权->消费商品1->唤醒第一个进入线程池的t1、t3而后阻塞、t1取得资格,若同样取得资格t4抢到执行权->t4阻塞->t1取得执行权->生产商品2->唤醒t2、t2取得执行权后不再判断flag真假直接生产t3。

于是将if判断改为while循环,这样的确弥补了错误。但会导致t2"醒来"->判断flag真假->t2进入阻塞状态。造成了所有线程全部等待。于是使用notifyAll();总是唤醒全部线程。又一次解决了问题。

JDK1.5提供了多线程升级解决方案,将同步synchronized替换成现实lock操作,要为特定 Lock 实例获得 Condition 实例,使用其 newCondition() 方法。

Condition 实例实质上被绑定到一个锁上。Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,

以便通过将这些对象与任意 Lock 实现组合使用。

改动后的代码:

import java.util.concurrent.locks.*;class Resource{    private String name;    private int count = 1;    private boolean flag = false;    private Lock lock = new ReentrantLock();    //将多个condition对象绑定到同一个锁上    private Condition condition_pro = lock.newCondition();    private Condition condition_con = lock.newCondition();        public void set(String name)throws InterruptedException    {        lock.lock();        try        {            while(flag)            condition_pro.await();            this.name = name +"---"+count++;            System.out.println(Thread.currentThread().getName()+"...producer..."+this.name);            flag = true;            condition_con.signal();    //唤醒对方        }        finally        {            lock.unlock();        }                }    public void out() throws InterruptedException    {        lock.lock();        try        {            while(!flag)                condition_con.await();            System.out.println(Thread.currentThread().getName()+"...consumes..."+this.name);            flag = false;            condition_pro.signal();        }        finally        {            lock.unlock();        }    }}class Producer implements Runnable{    private Resource res;    Producer(Resource res)    {        this.res = res;    }    public void run()    {        while(true)        {            try            {                res.set("+商品+");            }            catch (InterruptedException e)            {            }        }    }}class Consumer implements Runnable{    private Resource res;    Consumer(Resource res)    {        this.res = res;    }    public void run()    {        while (true)        {            try            {                res.out()            }            catch (InterruptedException e)            {            }        }    }}


0 0
原创粉丝点击