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

AQS Condition使用

作者头像
黑洞代码
发布2021-01-14 15:14:46
3930
发布2021-01-14 15:14:46
举报

标题

概述


1.Condition简单使用

2.Condition生产者消费者模型

第1节 Condition简单使用


Condition使用方式如下。

代码语言:javascript
复制
public class ConditionDemo {
    /**
     * 获取独占锁
     */
    private ReentrantLock lock = new ReentrantLock();
    /**
     * 获取条件1
     */
    private Condition condition1 = lock.newCondition();
    /**
     * 获取条件2
     */
    private Condition condition2 = lock.newCondition();
    /**
     * 获取条件3
     */
    private Condition condition3 = lock.newCondition();
    /**
     * 日期格式化
     */
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss");

    public static void main(String[] args) throws InterruptedException {
        ConditionDemo conditionDemo = new ConditionDemo();
        // Alibaba Java Coding Guidelines plugin 插件提示不要直接使用Executors
        ExecutorService executorService = Executors.newCachedThreadPool();
        Thread1 thread1 = conditionDemo.new Thread1();
        Thread2 thread2 = conditionDemo.new Thread2();
        Thread3 thread3 = conditionDemo.new Thread3();
        // 启动线程任务1、2、3.
        executorService.execute(thread1);
        executorService.execute(thread2);
        executorService.execute(thread3);
        Thread.sleep(2000);
        // 依次唤醒各线程任务.
        signalTest(conditionDemo);
        executorService.shutdown();
    }

    /**
     * 依次唤醒各线程任务,以观察condition的作用
     *
     * @param conditionDemo ConditionDemo对象
     * @throws InterruptedException 中断异常
     */
    public static void signalTest(ConditionDemo conditionDemo) throws InterruptedException {
        // 获取独占锁 唤醒condition1的线程
        conditionDemo.lock.lock();
        conditionDemo.condition1.signal();
        // 释放独占锁 等待thread1执行完毕.
        conditionDemo.lock.unlock();
        Thread.sleep(2000);

        // 获取独占锁 唤醒condition2的线程
        conditionDemo.lock.lock();
        conditionDemo.condition2.signal();
        // 释放独占锁 等待thread2执行完毕.
        conditionDemo.lock.unlock();
        Thread.sleep(2000);

        // 获取独占锁 唤醒condition3的线程
        conditionDemo.lock.lock();
        conditionDemo.condition3.signal();
        // 释放独占锁 等待thread2执行完毕.
        conditionDemo.lock.unlock();
        Thread.sleep(2000);
    }

    /**
     * 线程任务定义类
     */
    public class Thread1 implements Runnable {

        public Thread1() {

        }

        @Override
        public void run() {
            try {
                // 设置线程名称
                Thread.currentThread().setName(Thread1.class.getSimpleName());
                System.out.printf("%s线程启动\n", Thread.currentThread().getName());
                lock.lock();
                // 在condition1上阻塞,并且释放独占锁lock.
                condition1.await();
                System.out.printf("%s线程被唤醒", Thread.currentThread().getName());
                printDate();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 线程任务定义类
     */
    public class Thread2 implements Runnable {
        public Thread2() {

        }

        @Override
        public void run() {
            try {
                Thread.currentThread().setName(Thread2.class.getSimpleName());
                System.out.printf("%s线程启动\n", Thread.currentThread().getName());
                lock.lock();
                // 在condition2上阻塞,并且释放独占锁lock.
                condition2.await();
                System.out.printf("%s线程被唤醒", Thread.currentThread().getName());
                printDate();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 线程任务定义类
     */
    public class Thread3 implements Runnable {
        public Thread3() {

        }

        @Override
        public void run() {
            try {
                Thread.currentThread().setName(Thread3.class.getSimpleName());
                System.out.printf("%s线程启动\n", Thread.currentThread().getName());
                lock.lock();
                // 在condition2上阻塞,并且释放独占锁lock.
                condition3.await();
                System.out.printf("%s线程被唤醒", Thread.currentThread().getName());
                printDate();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 打印时间
     */
    void printDate() {
        System.out.println("【当前时间:" + simpleDateFormat.format(new Date()) + "】");
    }
}

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

代码语言:javascript
复制
Thread2线程启动
Thread3线程启动
Thread1线程启动
Thread1线程被唤醒【当前时间:2019-11-07 11:11:59】
Thread2线程被唤醒【当前时间:2019-11-07 11:11:01】
Thread3线程被唤醒【当前时间:2019-11-07 11:11:03】

第2节 Condition生产者消费者模型


Condition实现生产者消费者模型如下。

代码语言:javascript
复制
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-10于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 348】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 350】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 363】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 373】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 374】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 385】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 395】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 395】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 396】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 405】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 406】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 406】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 406】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 407】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 416】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 417】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 417】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 417】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 417】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 417】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 418】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 420】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 420】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 420】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 428】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 428】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 428】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 429】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 429】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 429】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 430】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 430】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 432】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 432】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 438】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 439】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 440】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 440】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 440】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 440】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 441】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 441】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 442】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 445】生产一条数据
消费者获取到数据生产者pool-1-thread-6于【当前时间:2019-11-07 11:11:19 450】生产一条数据
消费者获取到数据生产者pool-1-thread-1于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-10于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-7于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-3于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-9于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-2于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-5于【当前时间:2019-11-07 11:11:19 451】生产一条数据
消费者获取到数据生产者pool-1-thread-8于【当前时间:2019-11-07 11:11:19 453】生产一条数据
消费者获取到数据生产者pool-1-thread-4于【当前时间:2019-11-07 11:11:19 455】生产一条数据
本文参与?腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-08,如有侵权请联系?cloudcommunity@tencent.com 删除

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

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

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

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