zoukankan      html  css  js  c++  java
  • Java多线程 ReentrantLock、Condition 实现生产者、消费者协作模式

    一、锁接口 Lock,ReadWriteLock:

      1、Lock,实现类有ReentractLock、WriteLock、ReadLock;

      2、ReadWriteLock,主要实现类是ReentrantReadWriteLock,有两个方法 writeLock()、readLock() ,返回值是 WriteLock,ReadLock,这两类继承与Lock接口;

      3、常用方法:

        lock()  /  unlock():获取/释放锁,lock()会阻塞直到成功

        lockInterruptibly():与lock() 不同的是它可以响应中断,如果被其他线程中断了,则抛出InterruptedException

        tryLock() / tyrLock(long time, TimeUnit unit):只是尝试获取锁,立即返回,返回值为 boolean。无参数不阻塞,有参数会根据设置的时间阻塞等待,如果发生中断抛出InterruptedException

        newCondition:新建一个条件,一个lock可以关联多个条件

    二、对比 ReentractLock 和 synchornized:

        相比synchronized,ReentractLock可以实现与synchronized 相同的语义,而且支持以非阻塞方法获取锁,可以响应中断,可以限时,更为灵活。不过,synchronized 的使用更为简单,写的代码更少,也不容易出错。

    三、Condition:

      锁用于解决竞态条件问题,条件是线程间的协作机制。显示锁与synchronized 相对应,而显式条件与wait/notify 相对应。wait/notify 与synchronized 配合使用,显式条件与显示锁配合使用。

      1、声明:Condition c = reentractLock.newCondition();

      2、常用方法:

        await() / signal():等待/通知,使用时需获取锁,await() 发生中断,抛出 InterruptedException,但中断标志位会被清空。awaitUniterruptibly() 不响应中断              

    四、ReentractLock、Condition 搭配使用:

    /**
     * ReentrantLock 显式锁
     *
     * Condition 显式条件
     *
     * 生产者、消费者协作模式
     */
    
    public class ReentrantLockTest {
    
        private  int e = 1;
    
        private  int num = 30;
    
        //private  BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(num);
    
        private Queue<Integer> queue = new ArrayDeque<>(num);
    
        private  Lock lock = new ReentrantLock();
    
        private  Condition queueFull = lock.newCondition();
    
        private  Condition queueEmpty = lock.newCondition();
    
        public static void main(String[] args) throws InterruptedException {
    
            ReentrantLockTest reentrantLockTest = new ReentrantLockTest();
    
            for(int i = 0; i < reentrantLockTest.num; i++){
                new Thread(() -> {
                    try {
                        reentrantLockTest.producer();
    
                        Thread.sleep((int)(Math.random() * 100));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }).start();
            }
    
            for(int i = 0; i < reentrantLockTest.num; i++){
                new Thread(() -> {
                    try {
                        reentrantLockTest.consumer();
                        Thread.sleep((int)(Math.random() * 100));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }).start();
            }
    
        }
    
        public  void producer() throws InterruptedException {
            lock.lockInterruptibly();
            try{
                while (queue.size() == num){
                    queueFull.await();
                }
    
                queue.add(e++);
                System.out.println("producer" + Arrays.toString(queue.toArray()));
                queueEmpty.signal();
            }finally {
                lock.unlock();
            }
    
        }
    
        public  void consumer() throws InterruptedException {
            lock.lockInterruptibly();
            try{
                while (queue.isEmpty()){
                    queueEmpty.await();
                }
    
                System.out.println("poll:" + queue.poll() + ",comsumer" + Arrays.toString(queue.toArray()));
                queueFull.signal();
            }finally {
                lock.unlock();
            }
    
        }
    
    }
  • 相关阅读:
    configure: error: C++ preprocessor "/lib/cpp" fails sanity check See `config.log' for more details
    php7安装swoole
    Navicat 连接Mysql 8.0以上版本报错1251的详细解决方案
    1130
    linux中的 /etc/profile文件centos7
    linux安装php遇到的No package 'sqlite3' found,解决方法:
    ll: command not found
    每日一题 为了工作 2020 0325 第二十三题
    每日一题 为了工作 2020 0324 第二十二题
    每日一题 为了工作 2020 0323 第二十一题
  • 原文地址:https://www.cnblogs.com/haiyangwu/p/10443818.html
Copyright © 2011-2022 走看看