zoukankan      html  css  js  c++  java
  • LinkedBlockingQueue中put源码分析

    查看源码得知:

    LinkedBlockingQueue采用是锁分离的技术

        //取出锁
        private final ReentrantLock takeLock = new ReentrantLock();
    
        //取出锁条件
        private final Condition notEmpty = takeLock.newCondition();
    
        //插入锁
        private final ReentrantLock putLock = new ReentrantLock();
    
        //插入锁条件
        private final Condition notFull = putLock.newCondition();
    

    查看put方法源码

     public void put(E e) throws InterruptedException {
            //判断元素为空
            if (e == null) throw new NullPointerException();
            //设置元素值
            int c = -1;
            //创建节点
            Node<E> node = new Node<E>(e);
            //获取插入锁
            final ReentrantLock putLock = this.putLock;
            //设置数量
            final AtomicInteger count = this.count;
            //尝试加锁
            putLock.lockInterruptibly();
            try {
                //判断如果这个数量等于容器数量说明容器满了
                while (count.get() == capacity) {
                    //等待
                    notFull.await();
                }
                //插入
                enqueue(node);
                //长度+1
                //这里获取的c应该是原本的数据,getAndIncrement相当于i++
                c = count.getAndIncrement();
                //判断其+1后是否小于容器体积
                if (c + 1 < capacity)
                    //小于则通知其他插入线程进行插入
                    notFull.signal();
            } finally {
                //解锁
                putLock.unlock();
            }
            //如果c==0表示本来没有元素,现在已经有元素了
            //所以必须将其queue中的等待释放
            if (c == 0)
                signalNotEmpty();
        }
    

      其中这句源码理解挺久的:为何要加入这句话呢?

    if (c == 0)
                signalNotEmpty();
    

     由于c为获取的是添加元素前的数据,判断为0说明之前该队列为空,导致take方法中的线程处于等待的状态,通过该方法可以使得其take方法中的等待线程释放,让其可以获取资源,如下c为获取的为原本queue长度

    //这里获取的c应该是原本的数据,getAndIncrement相当于i++
                c = count.getAndIncrement();
    
    signalNotEmpty方法     
     private void signalNotEmpty() {
    
            //获取取出锁
            final ReentrantLock takeLock = this.takeLock;
         //由于后面需要进行通知操作,所以得先获取锁
            takeLock.lock();
            try {
           //通知现在queue里面有元素了,大家可以来获取元素了
                notEmpty.signal();
            } finally {
           //解锁
                takeLock.unlock();
            }
        }
    

      

      

      

  • 相关阅读:
    常用功能测试点的测试用例
    如何设计功能测试测试用例
    管理小原则
    政党提供的公共产品是其存在的依据
    为什么人是根本?
    学问总分类
    和孩子沟通的开头常用语
    教育的核心对象是心中的那枚种子
    用目标激发动力,用计划控制落实,用梳理总结进行提高
    要想影响孩子第一位的是保证沟通畅通
  • 原文地址:https://www.cnblogs.com/lonecloud/p/8971106.html
Copyright © 2011-2022 走看看