前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AQS——Condition使用

AQS——Condition使用

作者头像
黑洞代码
发布2021-01-14 15:12:30
7260
发布2021-01-14 15:12:30
举报

AQS——Condition使用

概述


1.Lock & Condtion & AQS关系

2.Lock & Condtion & AQS类图

3.Condtion实现生产者消费者模型

第1节 Lock & Condtion & AQS关系


等待通知机制,在Java中主要有两种方式:

一是基于wait/notify方法结合synchronized关键字来实现。

二是Condition结合Lock来实现。

前面我们学习了synchronized同步代码块,了解了java的内置锁,并学习了监视器锁的wait/notify机制。在大多数情况下,内置锁都能很好的工作,但它在功能上存在一些局限性,例如无法实现非阻塞结构的加锁规则等。为了拓展同步代码块中的监视器锁,java 1.5 开始,出现了lock接口,它实现了可定时、可轮询与可中断的锁获取操作,公平队列,以及非块结构的锁。

与内置锁不同,Lock是一种显式锁,它更加“危险”,因为在程序离开被锁保护的代码块时,不会像监视器锁那样自动释放,需要我们手动释放锁。所以,在我们使用Lock锁时,一定要记得:

在finally块中调用lock.unlock()手动释放锁!!!

在finally块中调用lock.unlock()手动释放锁!!!

在finally块中调用lock.unlock()手动释放锁!!!

监视器锁与Condition方法对比如下图所示。

第2节 Lock & Condtion & AQS类图


Lock与Condtion和AQS关系密切。Condition相关的类图如下。

第3节 Condtion实现生产者消费者模型


通过Condition可使线程按照不同的条件进行等待和唤醒。通过Condition提供的方法替代Object类的wait()和notify()方法,实现更加定制化的生产者-消费者模型。

通过Condition实现生产者-消费者模型,代码实现如下。

代码语言:javascript
复制
/**
 * @Author: 【QQ:3190976240 email:zhouguanya20@163.com】
 * @Date: 2019-09-02 23:05
 * @Description: Condition实现生产者-消费者模型
 */
public class ProducerConsumer {
    /**
     * Lock
     */
    private final Lock lock = new ReentrantLock();
    /**
     * 数组未满
     */
    private final Condition notFull = lock.newCondition();
    /**
     * 数组非空
     */
    private final Condition notEmpty = lock.newCondition();
    /**
     * 存储数据的底层数组
     */
    private final Object[] items = new Object[100];
    /**
     * 输入数据的索引位置
     */
    private int inputIndex;
    /**
     * 输出数据的索引位置
     */
    private int outputIndex;
    /**
     * 计数器
     */
    private int count;
    /**
     * 日期格式化
     */
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss SSS");

    public static void main(String[] args) {
        ExecutorService executorService = null;
        try {
            // Alibaba Java Coding Guidelines plugin 插件提示不要直接使用Executors
            executorService = Executors.newCachedThreadPool();
            ProducerConsumer producerConsumer = new ProducerConsumer();
            // 10个生产者线程
            for (int i = 0; i < 10; i++) {
                executorService.submit(() -> {

                    for (int j = 0; j < 10; j++) {
                        try {
                            Thread.sleep(10);
                            producerConsumer.put(String.format("生产者%s于%s生产一条数据", Thread.currentThread().getName(), printDate()));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            // 1个消费者线程
            executorService.submit(() -> {
                try {
                    for (int i = 0; i < 100; i++) {
                        Object outPut = producerConsumer.take();
                        System.out.printf("消费者获取到数据%s%n", outPut);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        } finally {
            assert executorService != null;
            executorService.shutdown();
        }

    }

    /**
     * 生产者方法,往数组里面写数据
     *
     * @param input 输入数据
     * @throws InterruptedException 中断异常
     */
    public void put(Object input) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                //数组已满,没有空间时,挂起等待,直到数组“非满”(notFull)
                notFull.await();
            }
            items[inputIndex] = input;
            if (++inputIndex == items.length) {
                inputIndex = 0;
            }
            ++count;
            // 因为放入了一个数据,数组肯定不是空的了
            // 此时唤醒等待这notEmpty条件上的线程
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 消费者方法,从数组里面拿数据
     *
     * @return 数据
     * @throws InterruptedException 中断异常
     */
    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                // 数组是空的,没有数据可拿时,挂起等待,直到数组非空(notEmpty)
                notEmpty.await();
            }
            Object x = items[outputIndex];
            if (++outputIndex == items.length) {
                outputIndex = 0;
            }
            --count;
            // 因为拿出了一个数据,数组肯定不是满的了
            // 此时唤醒等待这notFull条件上的线程
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 打印时间
     */
    private static String printDate() {
        return "【当前时间:" + simpleDateFormat.format(new Date()) + "】";
    }
}

执行以上代码,执行结果如下。

代码语言:javascript
复制
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 519】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 519】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 521】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 519】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 536】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 547】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 547】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 546】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 548】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 557】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 558】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 558】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 558】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 568】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 571】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 580】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 582】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 591】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 595】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 602】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 603】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 606】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 612】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 612】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 612】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 613】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 617】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-09-29 11:09:12 624】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-09-29 11:09:12 625】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-09-29 11:09:12 625】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-09-29 11:09:12 630】生产一条数据
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 落叶飞翔的蜗牛 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

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