zoukankan      html  css  js  c++  java
  • ReentrantLock(重入锁)的好搭档:Condition 条件

    如果大家理解了Object.Wait()和Object.notify()方法的话,那么就会很容易的了解Condition对象了;它和wait()和notify()方法的作用是一致的,但是wait()和notify()是和synchronized关键字合作使用的,而Condition是和ReentrantLock(重入锁)相关联的。

    通过ReentrantLock锁的 new Condition() 方法可以生成一个与当前锁相关联的Condition实例。利用Condition对象,我们就可以让线程在合适的时候等待,或者在某一个特定的时刻让线程得到通知,继续执行。

    Condition接口提供的基本方法如下:

    1 void await() throws InterruptedException;
    2 void awaitUninterruptibly();
    3 long awaitNanos(long nanosTimeout) thows InterruptedException;
    4 boolean await(long time,TimeUnit unit) throws InterruptedException;
    5 boolean awaitUntil(Date deadline) throws InterruptedException;
    6 void signal();
    7 void signalAll();

    以上方法的含义如下:

      ❤ await()方法会使当前线程等待,同时释放当前锁,当其他线程使用signal()或者signalAll()方法时,线程会重新获得锁并继续执行。或者当线程被中断时,也能跳出等待,这和Object.wait()方法很相似;

      ❤ awaitUninterruptibly()方法与await()方法基本相同,但是它不会在等待过程中响应中断;

      ❤ awaitNanos(long nanosTimeout) nanosTimeout为等待的最大时间,单位为纳秒(ns),如果在时间内被唤醒,则返回nanosTimeout减去已等待的时间;如果在时间内没有被唤醒,则返回0或者负数;该方法在等待时间内也会相应中断;

      ❤ await(long time,TimeUnit unit) 与await()基本一致,但不同的是在时间内未被唤醒或者被中断都会返回false,其余情况返回true;

      ❤ awaitUntil() 与awaitNanos(long nanosTimeout)一致,不同的是它不是等待时间段,而是时间到达参数指定的某一时刻;

      ❤ signal()方法用于唤醒一个在等待中的线程。相对的signalAll()方法会唤醒所有在等待中的线程,这和Object.notify()方法很类似;

    下面演示下Condition的用法:

     1 public class ReentrantLockCondition implements Runnable {
     2 
     3     public static ReentrantLock lock = new ReentrantLock();
     4     public static Condition condition = lock.newCondition();
     5 
     6     @Override
     7     public void run() {
     8         try {
     9             lock.lock();
    10             System.out.println("Thread is waiting! : " + System.currentTimeMillis());
    11             condition.await();
    12             System.out.println("Thread is going on! : " + System.currentTimeMillis());
    13         } catch (InterruptedException e) {
    14             e.printStackTrace();
    15         }finally {
    16             lock.unlock();
    17         }
    18     }
    19     //测试
    20     public static void main(String[] args) throws InterruptedException {
    21         ReentrantLockCondition reen = new ReentrantLockCondition();
    22         Thread thread = new Thread(reen);
    23         thread.start();
    24         Thread.sleep(3000);
    25         //通知线程reen继续执行
    26         lock.lock();
    27         condition.signal();
    28         lock.unlock();
    29     }
    30 }

    输出结果:

    1 Thread is waiting! : 1537841252752
    2 Thread is going on! : 1537841255753

     在代码的第4行,通过lock生成一个与之绑定的Confition对象,并在代码的第11行,要求线程在Condition对象上进行等待。代码的第27行,由main线程发出通知,告知等待Condition上的线程可以继续执行了;由输出结果来看,线程等待了3S后,继续执行了,符合我们预期。

    注意:

      和Object.wait()和notify()方法一样,当线程使用Condition.await()时,要求线程持有相关的重入锁,在Condition.await()调用后,这个线程会释放这把锁;同理,在Condition.signal()方法调用时,也要求线程获得相应的锁。在signal()方法调用后,系统会从当前Condition对象的等待队列中,唤醒一个线程。一旦线程被唤醒,它会重新尝试获得与之绑定的重入锁,一旦获取成功,就可以继续执行了。因此在signal()方法调用后,一般需要释放相关的锁,如果省略掉代码的第28行,那么虽然唤醒了线程reen,但是由于线程无法重新获得锁,因而也就无法继续执行。

    Condition具有比wait()/notify()更好的灵活性,具体体现在:

      ❤ 一个锁实例,可以绑定多个Condition实例,实现多路通知;

      ❤ notify()方法进行通知时,是随机进行选择的,但重入锁结合Condition对象,可以实现有选择性的通知,这是非常重要的。

    参考:《Java高并发程序设计》葛一鸣  郭超 编著:

    作者:Joe
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    Educational Codeforces Round 20 D. Magazine Ad
    Educational Codeforces Round 20 C. Maximal GCD
    紫书第三章训练2 暴力集
    Educational Codeforces Round 20 B. Distances to Zero
    Educational Codeforces Round 20 A. Maximal Binary Matrix
    紫书第三章训练1 D
    紫书第一章训练1 D -Message Decoding
    HAZU校赛 Problem K: Deadline
    Mutual Training for Wannafly Union #8 D
    紫书第三章训练1 E
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/9698353.html
Copyright © 2011-2022 走看看