Lock - condition

Condition

之前文章有写wait/notify/notifyAll

Condition作用类似,可能会多一些功能 比如:支持不响应中断、可指定时间点结束等待、可多条件(new 多个Condition)

Condition的await 与wait类似 必须在获取锁的时候才能await

一、 使用

/**
 * @author 木子的昼夜
 */public class ConditionTest {public static Lock lock = new ReentrantLock();//public static Condition cd01 = lock.newCondition();public static void main(String[] args) throws InterruptedException {ConditionTest test = new ConditionTest();new Thread(test::say01).start();Thread.sleep(5000);new Thread(test::say02).start();}/**
     * 说:我饿了
     */public void say01(){try{lock.lock();System.out.println("我饿了");cd01.await();System.out.println("吃饱了");} catch (Exception e){e.printStackTrace();} finally {lock.unlock();}}/**
     * 说:饭好了
     */public void say02(){try{lock.lock();cd01.signal();System.out.println("开饭了");} catch (Exception e){e.printStackTrace();} finally {lock.unlock();}}}输出结果:
我饿了
开饭了
吃饱了

二、 不响应中断

看一下say01 say02 可中断 say03 不可中断

public class ConditionTest02 {public static Object obj = new Object();public static Lock lock = new ReentrantLock();public static Condition cd01 = lock.newCondition();public static void main(String[] args) throws InterruptedException {ConditionTest02 test = new ConditionTest02();Thread thread = new Thread(test::say01);Thread thread02 = new Thread(test::say02);Thread thread03 = new Thread(test::say03);thread.start();thread02.start();thread03.start();// 饿他们5秒钟Thread.sleep(5000);// 中断thread.interrupt();thread02.interrupt();// say03会中断失败thread03.interrupt();}/**
     * 说:小强饿了
     */public void say01(){try{lock.lock();System.out.println("小强饿了");System.out.println("小强等待投食");cd01.await();System.out.println("小强吃饱了");}catch (InterruptedException e){System.out.println("小强出去觅食了");}catch (Exception e){e.printStackTrace();} finally {lock.unlock();}}/**
     * 说:小明饿了
     */public void say02(){try{synchronized (obj){System.out.println("小明饿了");System.out.println("小明等待投食");obj.wait();System.out.println("小明吃饱了");}} catch (InterruptedException e){System.out.println("小明出去觅食了");}}/**
     * 说:小月鸟饿了 中断无用 
     */public void say03(){try{lock.lock();System.out.println("小月鸟饿了");System.out.println("小月鸟等待投食");cd01.awaitUninterruptibly();System.out.println("小月鸟吃饱了");}catch (Exception e){System.out.println("小月鸟出去觅食了");e.printStackTrace();} finally {lock.unlock();}}
   }输出结果:
小明饿了
小明等待投食
小强饿了
小强等待投食
小月鸟饿了
小月鸟等待投食
小明出去觅食了
小强出去觅食了

三、 超时停止wait

condition可以await一段时间 自己意识到 没人理他 然后就结束await了

Object的wait也可以指定超时时间

public class ConditionTest03 {public static Lock lock = new ReentrantLock();//public static Condition cd01 = lock.newCondition();public static void main(String[] args)   {ConditionTest03 test = new ConditionTest03();new Thread(test::say01).start();}/**
     * 说:我饿了
     */public void say01(){try{lock.lock();System.out.println("我饿了");System.out.println("等待投喂");//// 这个需要的单位是毫微妙  也就是秒*1000*1000000  也就是5000000000L毫微妙 = 5秒// 也可以这样获取 nanos就等于 也就是5000000000Llong nanos = TimeUnit.SECONDS.toNanos(5);long res = cd01.awaitNanos(5000000000L);// 也可以这样 返回true  false // boolean res = cd01.await(10,TimeUnit.SECONDS);// 超时if (res <= 0){System.out.println("没人投喂  我自己觅食去");} else {System.out.println("有人投喂 我吃饱了");}} catch (Exception e){e.printStackTrace();} finally {lock.unlock();}}}

四、指定时间

可以指定到指定某个时间点 就结束wait

public class LockTest04 {// 新建锁public static Lock lock = new ReentrantLock(false);public static Condition cd = lock.newCondition();public static void main(String[] args) throws InterruptedException {new Thread(()->{try {lock.lock();long l = System.currentTimeMillis();l = l +1000*10;Date date = new Date(l);boolean  res = cd.awaitUntil(date);if(res) {System.out.println("被通知");} else {System.out.println("没人通知  到时见我自己走了");}} catch (Exception e){e.printStackTrace();}finally {lock.unlock();}}).start();}}

五、 创建多个condition

这里举个例子:小强 和 小月月 两个人在玩儿玩具 小强玩会儿 不玩儿了给小月月 小月月不玩了再给小强

public class PlayTest {public static Lock lock = new ReentrantLock();public static Condition cd01 = lock.newCondition();public static void main(String[] args) {PlayTest test = new PlayTest();new Thread(test::xiaoqiangPlay).start();new Thread(test::xiaoxuexuePlay).start();}// 小强玩儿public void xiaoqiangPlay(){try {while (true){lock.lock();System.out.println("小强玩儿");Thread.sleep(5000);// 通知别人玩儿cd01.signal();// 自己等着别人通知cd01.await();}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}// 下月月玩public void xiaoxuexuePlay(){try {while(true){lock.lock();System.out.println("小月月玩儿");Thread.sleep(5000);// 通知别人玩儿cd01.signal();// 自己等着别人通知cd01.await();}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}

可以使用两个condition

public class PlayTest02 {public static Lock lock = new ReentrantLock();public static Condition cd01 = lock.newCondition();public static Condition cd02 = lock.newCondition();public static void main(String[] args) {PlayTest02 test = new PlayTest02();new Thread(test::xiaoqiangPlay).start();new Thread(test::xiaoxuexuePlay).start();}// 小强玩儿public void xiaoqiangPlay(){try {while (true){lock.lock();System.out.println("小强玩儿");Thread.sleep(5000);// 通知别人玩儿cd01.signal();// 自己等着别人通知cd02.await();}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}// 下月月玩public void xiaoxuexuePlay(){try {while(true){lock.lock();System.out.println("小月月玩儿");Thread.sleep(5000);// 通知别人玩儿cd02.signal();// 自己等着别人通知cd01.await();}} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}}

两个condition互不干扰,可以指定condition await / signal

condition的signalAll 与 notifyAll 类似 不再代码演示

六、总结

  1. 创建Condition (可创建多个 互不影响)
  2. 必须在lock获取锁之后才能使用
  3. await 支持不相应中断、超时(Object wait也支持)、指定时间点结束
  4. signal只会唤醒一个线程 signalAll 会唤醒所有线程


上一篇:Condition源码分析


下一篇:csmarapi