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
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    Flink 双流合并之connect Demo2
    Flink 双流合并之connect Demo1
    Flink 双流合并Join
    Flink状态保存CheckPoint
    Flink状态之OperatorState
    Flink状态之AggregateState
    Flink状态之ReduceState
    Flink状态之MapState
    Flink状态之KeyedListState
    大数据框架环境安装与配置01--服务器基本设置
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/9698353.html
Copyright © 2011-2022 走看看