Java线程之1.5版新特性多生产者多消费者(四)

来源:互联网 发布:施工图设计优化 编辑:程序博客网 时间:2024/05/29 17:46

在Java1.5以前的版本中,因为监视器是来自于Object,为了线程的互斥访问,用的synchronized方法或者模块

  • 在synchronized中,“锁”的操作是隐式的,而且每一个锁里只能有一组wait-notify或是wait-notifyAll方法,这样的弊端在于
    等待和唤醒的缓冲线程里不仅包括了生产者也包括了消费者,这样就不能指定唤醒进程,要么唤醒了全部进程,影响了效率,要么休眠了所有进程,发生死锁

Java从1.5版本开始支持新的”锁“,体现的面向对象的特点,将锁封装起来

  • Lock实例可以通过Condition挂载多个监视器
    Condition c1 = lock.newCondition();
    Condition c2 = lock.newCondition();
    Condition中的await(),signal() ,signalAll() 来替换对应Object对象锁的方法

这样就可以实现一个锁,而指定唤醒对方进程,避免死锁,提高执行效率

java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。

java.util.concurrent.locks
接口 Lock
所有已知实现类:
ReentrantLock,ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock

  • 关于ReentrantLock
    一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

其实就是synchronized的隐形锁换成了Lock中的显示锁及显示操作

void method(){{    synchronized (obj)//对象锁        {            //code...        }}

改了形式

Lock lock = new ReentrantLock();//void method(){    try    {        lock.lock();//显示获取锁        code...throw Exception();//因为可能发生中断异常,所以把管闭锁的动作放到finally中    }    finally    {        lock.unlock();    }

eg:

mport java.util.concurrent.locks.*;class Resource{    String name;    private int count = 1;    String id ;    private boolean flag = false;//初始默认没有产品    //创建锁    Lock lock = new ReentrantLock();    //通过已有的锁创建两个监视,分别监视生产者和消费者    Condition cp = lock.newCondition();//生产者监视器    Condition cc = lock.newCondition();//消费者监视器    public  void producer(String name)    {        try        {            lock.lock();            while(flag)            try{cp.await();} catch (InterruptedException ex){}//生产者等待            this.name = name;            id = name + count++;            System.out.println(Thread.currentThread().getName()+"--->生产:"+id);            flag = true;            cc.signal();//唤醒消费者        }        finally         {            lock.unlock();        }    }    public void consumer()    {        try        {            lock.lock();            while(!flag)            try{cc.await();} catch (InterruptedException ex){}//消费者等待           System.out.println(Thread.currentThread().getName()+"--------->消费"+id);           flag = false;           cp.signal();//唤醒生产者        }        finally         {            lock.unlock();        }    }}class Producer implements Runnable{    Resource r;    Producer(Resource r)    {        this.r = r;    }    public void run()    {        while(true)        {            r.producer("包子");        }    }}class Consumer implements Runnable{    Resource r;    Consumer(Resource r)    {        this.r = r;    }    public void run()    {        while (true)        {            r.consumer();        }    }}class ThreadPC3{    public static void main(String[] args)     {        //创建资源        Resource r = new Resource();        //创建线程任务        Producer p0 = new Producer(r);        Producer p1 = new Producer(r);        Consumer c0 = new Consumer(r);        Consumer c1 = new Consumer(r);        //创建线程        Thread tp0 = new Thread(p0);        Thread tp1 = new Thread(p1);        Thread tc0 = new Thread(c0);        Thread tc1 = new Thread(c1);        //开启线程        tp0.start();        tp1.start();        tc0.start();        tc1.start();    }}

这里写图片描述

这个是API中的例子:

这个不用自己实现,已经封装的

class BoundedBuffer {   final Lock lock = new ReentrantLock();   final Condition notFull  = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];   int putptr, takeptr, count;   public void put(Object x) throws InterruptedException {     lock.lock();     try {       while (count == items.length)          notFull.await();       items[putptr] = x;        if (++putptr == items.length) putptr = 0;       ++count;       notEmpty.signal();     } finally {       lock.unlock();     }   }   public Object take() throws InterruptedException {     lock.lock();     try {       while (count == 0)          notEmpty.await();       Object x = items[takeptr];        if (++takeptr == items.length) takeptr = 0;       --count;       notFull.signal();       return x;     } finally {       lock.unlock();     }   }  }
1 0