前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >话说 Lock condition

话说 Lock condition

原创
作者头像
木子的昼夜
修改2021-04-06 11:09:33
5110
修改2021-04-06 11:09:33
举报

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就等于 也就是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 会唤醒所有线程

欢迎关注公众号:

公众号二维码.jpg
公众号二维码.jpg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Condition
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档