设为首页 加入收藏

TOP

Condition java1.8
2019-03-19 12:02:07 】 浏览:53
Tags:Condition java1.8
版权声明:转载 请标注 出处 https://blog.csdn.net/youyou1543724847/article/details/52168980

昨天看了PriorityBlockingQueue,里面有一个Condition notEmpty变量,觉得挺奇怪的,今天,翻一翻API,了解一下。


目录
1.Condition是什么
Condition实际上就是将Ojbect对象的监视器(wait,notity)功能抽象出来了,从而允许形成多个等待队列。
之前的使用Object的wait方法,则将当前线程阻塞到该object的等待队列上。Condition也是为了实现类似的功能,在await时,释放当前拥有的锁,在signal时,唤醒某个线程(也是不能确定是那个线程)


2.Why Condition
可以形成多个不同条件的和锁关联的等待队列,从而更加灵活。对比Object的wait,notify只能形成一个等待队列(关于这个说明,见下面的例子)


3.例子
一个有界缓冲区的例子:当缓冲区满、空时,阻塞相应的放、取线程。

 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();
     }
   }
 }

使用Condition的好处是在一把锁上,形成两个等待队列。
有人又要问了,这里用了两个Condition,如果我用两个Ojbect对象,不是也能达到形成两个等待队列的效果么?
关于这个问题,我的理解是这样的:
a:你用两个object对象,是能形成两个等待队列,但是这两个等待队列是没有关系的。
b:你要调用object的wait,notify方法,你只能结合synchronzied使用,且你必须先要获取这些对象的锁,才能使用,这非常的烦琐。先不说不能使用lock带来的好处,先看看这样的代码可能是什么样子:

因为你要保护存储数据的items字段,保证只能有一个线程能够访问,则相应的方法就需要用synchronzed修饰(或是右创建一个obect对象,然后,用它来保护items对象)。另外,你需要操作notfull,notempty两个等待队列,那么需要首先获得这两把锁。

   final Object notFull  = new Object();
   final Object notEmpty = new Object();

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   synchronized public  void put(Object x) throws InterruptedException {
       synchronized(notFull)
       {
           synchronized(notEmpty)
           {
               while (count == items.length)
                 notFull.wait();
               items[putptr] = x;
               if (++putptr == items.length) putptr = 0;
               ++count;
               notEmpty.notify();
           } 
       }
   }

分析一下:如果B一开始去取,当前缓冲区为空,失败,等待在notEmpty上。然后A线程调用了put,没有问题(B已经释放了锁),缓冲区不为空了,唤醒B。接着A一直调用put,直到缓存区满了,这时A会阻塞在notfull队列上,然后释放已经获得的锁。。。。
小节一下:这下比较清楚Condition的优势了吧,根据一把锁,形成多个等待队列。而Object的方法是一个锁,一个队列,如果要形成多个队列,则要形成多把锁。且Ojbect是和Synchronized结合使用的。


4.结合PriorityBlockingQueue看一眼用法
构造方法中创建相应的锁和condition对象

    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator< super E> comparator) 
    {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }

在插入后 调用:notEmpty.signal();
在取的时候调用: while ( (result = dequeue()) == null)
notEmpty.await();
(因为该queue是无界的,在插入时,是永远可以的)


5.总结
a:和lock绑定,形成多个等待队列(只能和lock联合使用,通过lock.newCondition方法生成实例对象)

b:要写好一篇好不容易,以前觉得只要打打字就完了,现在发现我找了上面的按钮半天,也没有发现有个字体颜色的菜单,郁闷啊。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇未完待续   HDFS中使用had.. 下一篇整数的拆分2

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目