zoukankan      html  css  js  c++  java
  • Condition接口简介

    本博客系列是学习并发编程过程中的记录总结。由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅。

    并发编程系列博客传送门

    接口简介

    Condition可以看做是Obejct类的wait()notify()notifyAll()方法的替代品,与Lock配合使用。
    当线程执行condition对象的await方法时,当前线程会立即释放锁,并进入对象的等待区,等待其它线程唤醒或中断。

    JUC在实现Conditon对象时,其实是通过实现AQS框架,来实现了一个Condition等待队列,这个在后面讲AQS框架时会详细介绍,目前只要了解Condition如何使用即可。

    接口定义

    public interface Condition {
    
        void await() throws InterruptedException;
    
        long awaitNanos(long nanosTimeout) throws InterruptedException;
        
        boolean await(long time, TimeUnit unit) throws InterruptedException;
    
        boolean awaitUntil(Date deadline) throws InterruptedException;
    
        void signal();
    
        void signalAll();
    }
    

    使用示例

    wait-notify模式的一个典型应用就是可以实现生产者-消费者模式。让我印象很深是我毕业那年阿里巴巴校园招聘的一个笔试题:

    有一个苹果箱,有10个人向这个箱子中每次随机放入一个苹果,有10个人每次随机从这个箱子中随机拿走一个苹果,同时需要满足箱子中的苹果总数不能超过50个。请用代码实现上面的场景(不能使用并发集合框架)

    这个题目使用wait-notify模式可以很好地解决。下面使用Condition模式来写下。

    public class AppleBoxConditon {
    
        private int appleCount;
        private static Lock lock = new ReentrantLock();
        private static Condition fullCondition = lock.newCondition();
        private static Condition emptyCondition = lock.newCondition();
    
        public void putApple() {
            lock.lock();
            try {
                while (appleCount >= 10) {
                    try {
                        fullCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                appleCount++;
                System.out.println("放入一个,当前盒子中苹果数:" + appleCount);
                emptyCondition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    
    
        public void takeApple() {
            lock.lock();
            try{
                while (appleCount <= 0) {
                    try {
                        emptyCondition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                appleCount--;
                System.out.println("拿走一个,当前盒子中苹果数:" + appleCount);
                fullCondition.signalAll();
            }finally {
                lock.unlock();
            }
        }
    
        private static class AppleTaker implements Runnable {
    
            private AppleBoxConditon appleBox;
    
            public AppleTaker(AppleBoxConditon appleBox) {
                this.appleBox = appleBox;
            }
    
            @Override
            public void run() {
                while (true) {
                    appleBox.takeApple();
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
        private static class ApplePutter implements Runnable {
    
            private AppleBoxConditon appleBox;
    
            public ApplePutter(AppleBoxConditon appleBox) {
                this.appleBox = appleBox;
            }
    
            @Override
            public void run() {
                while (true) {
                    appleBox.putApple();
                    try {
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
        public static void main(String[] args) {
            AppleBoxConditon appleBox = new AppleBoxConditon();
    
    
            for (int i = 0; i < 20; i++) {
                Thread t = new Thread(new AppleBoxConditon.ApplePutter(appleBox));
                t.setName("ApplePutter:"+i);
                t.start();
            }
    
            for (int i = 0; i < 20; i++) {
                Thread t = new Thread(new AppleBoxConditon.AppleTaker(appleBox));
                t.setName("AppleTaker:"+i);
                t.start();
            }
    
        }
    
    }
    
  • 相关阅读:
    SPOJ ADAFIELD Ada and Field(STL的使用:set,multiset,map的迭代器)题解
    hdu 6444 网络赛 Neko's loop(单调队列 + 裴蜀定理)题解
    hdu6446 网络赛 Tree and Permutation(树形dp求任意两点距离之和)题解
    HDU6447 网络赛 YJJ's Salesman(DP + 线段树)题解
    HDU 6438 网络赛 Buy and Resell(贪心 + 优先队列)题解
    BZOJ 3155 Preprefix sum
    BZOJ 2743 采花
    BZOJ 3339 Rmq Problem
    BZOJ 1660 乱发节
    BZOJ 3531 旅行
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/12674541.html
Copyright © 2011-2022 走看看