• 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();
            }
        }
    

      

      

      

  • 相关阅读:
    张艾迪:全面开放“A"计划
    张艾迪(创始人):我们是激情与开放的世界
    张艾迪(创始人):由产品集合到创新的引领
    张艾迪(创始人):Be.Time+Cr.Idear的创新理念
    张艾迪(创始人): 整合全新的UIW.AD概念
    张艾迪(创始人): 整合全新的UIW.AD概念模式
    腾讯会员免费领取试用免费腾讯视频vip共享
    golang二进制bit位的常用操作
    golang ntp协议客户端
    imagecreatefrombmp、imagebmp php处理bmp文件
  • 原文地址:https://www.cnblogs.com/lonecloud/p/8971106.html
Copyright © 2020-2023  润新知