写点什么

话说 Lock condition

发布于: 2021 年 04 月 05 日

之前文章有写 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就等于 也就是5000000000L long 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 会唤醒所有线程

用户头像

还未添加个人签名 2018.03.28 加入

还未添加个人简介

评论

发布
暂无评论
话说  Lock condition