zoukankan      html  css  js  c++  java
  • Java Condition

    Java中对线程的阻塞和唤醒有两种机制

    一、通过Object的wait和notify结合synchronized关键字实现

    二、Condition集合Lock

    本文介绍第二种

    Condition特性

    • 类似于Object的wait和notify机制,但不同在于,Condition是需要关联Lock对象,通过Lock对象的newCondition()创建
    • 可精细控制多线程,同一个锁,可以创建多个Condition

        例如:多线程读/写一块堆内存缓存区,生成者消费者模式,通过Condition可以明确唤醒哪个线程

    例子

    package com.darchrow.test.condition;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * 例子说明:
     * add()方法:当集合长度为10时,就挂起当前的线程, 让其他线程先走。否则就会添加一条信息,然后唤起执行sub()的线程
     * sub()方法:当长度为0时,同理操作
     *
     * @author mdl
     * @date 2020/3/25 10:08
     */
    public class ConditionDemo implements Runnable {
    
        private final static Lock lock = new ReentrantLock();
    
        private final static Condition addCondition = lock.newCondition();
    
        private final static Condition subCondition = lock.newCondition();
    
    
        private static int num = 0;
    
        private static List<String> list = new LinkedList<>();
    
        private boolean flag;
    
        private CountDownLatch countDwonLatch;
    
        public ConditionDemo(boolean flag, CountDownLatch countDwonLatch) {
            this.flag = flag;
            this.countDwonLatch = countDwonLatch;
        }
    
        private void add() {
            lock.lock();
            try {
                if (list.size() == 10) {
                    // 集合满了,不能再加了,等待减
                    addCondition.await();
                }
                // 没满,可以继续添加元素
                num++;
                list.add("add banana" + num);
                System.out.println("当前线程:" + Thread.currentThread().getName() + ", 向集合里加入元素, 目前长度" + list.size());
                // 加完了,可以减了
                subCondition.signal();
                countDwonLatch.countDown();
                System.out.println("当前线程:" + Thread.currentThread().getName() + "countDownLatch.getCount()=" + countDwonLatch.getCount());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
    
        private void sub() {
            lock.lock();
            try {
                if (list.size() == 0) {
                    // 集合空了,阻塞,不能再减了,等待
                    subCondition.await();
                }
                // 有数据了,可以减
                num--;
                String str = list.get(0);
                list.remove(0);
                System.out.println("当前线程:" + Thread.currentThread().getName() + ", 集合减元素, " + str + ",减少后长度" + list.size());
                // 减完了,可以继续加了
                addCondition.signal();
                countDwonLatch.countDown();
                System.out.println("当前线程:" + Thread.currentThread().getName() + "countDownLatch.getCount()=" + countDwonLatch.getCount());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
    
        }
    
    
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDwonLatch = new CountDownLatch(40);
            ConditionDemo ConditionDemo1 = new ConditionDemo(true, countDwonLatch);
            ConditionDemo ConditionDemo2 = new ConditionDemo(false, countDwonLatch);
            ExecutorService executorService1 = Executors.newFixedThreadPool(10);
            ExecutorService executorService2 = Executors.newFixedThreadPool(10);
    
            for (int i = 0; i < 20; i++) {
                executorService1.execute(ConditionDemo1);
                executorService2.execute(ConditionDemo2);
            }
            countDwonLatch.await();
            executorService1.shutdown();
            executorService2.shutdown();
    
            System.out.println("最终集合元素个数:" + list.size());
    
    //        Thread t1 = new Thread(ConditionDemo1);
    //        Thread t2 = new Thread(ConditionDemo1);
    //        Thread t3 = new Thread(ConditionDemo1);
    //        Thread t4 = new Thread(ConditionDemo1);
    //        Thread t5 = new Thread(ConditionDemo1);
    //
    //        Thread t6 = new Thread(ConditionDemo2);
    //        Thread t7 = new Thread(ConditionDemo2);
    //        Thread t8 = new Thread(ConditionDemo2);
    //        Thread t9 = new Thread(ConditionDemo2);
    //
    //        t1.start();
    //        t2.start();
    //        t3.start();
    //        t4.start();
    //        t5.start();
    //        t6.start();
    //        t7.start();
    //        t8.start();
    //        t9.start();
    
        }
    
        @Override
        public void run() {
            if (flag) {
                add();
            } else {
                sub();
            }
    
        }
    }
    每一步脚印都要扎得深一点!
  • 相关阅读:
    Sql语句中IN和exists的区别及应用
    时间戳/Date(1354116249000)/ 转换
    SqlServer不允许更改字段类型(表中已有数据)
    Firefox内存占用过高解决方法
    接口开发中的测试问题
    c# winform 窗体起始位置 设置
    【整理】C#文件操作大全(SamWang)
    C#实现JSON序列化与反序列化
    解决方案资源管理器中跟踪活动项
    C#中方法的参数的四种类型
  • 原文地址:https://www.cnblogs.com/bloodthirsty/p/12566669.html
Copyright © 2011-2022 走看看