JUC---各大queue的特点

1.queue常用方法:

remove:从队列中删除第一个元素,不存在报错。
poll:从队列中删除第一个元素,不存在返回null。

peek:查询第一个元素,不存在返回null。

add:往队列加一个元素,队列满报异常。
offer:往队列加一个元素,队列满返回false;
put: 往队列加一个元素,队列满时阻塞,直到队列有新的空间。
take:从队列中拿取第一个元素,队列为空则阻塞到队列有元素为止。

 

2.ArrayBlockingQueue源码:

 

2.1 add与offer:

    public boolean add(E e) {
        return super.add(e);
    }


    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length) //判断队列是否满
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

    private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();  //唤醒等待线程
    }

2.2 put && take:

//put 
   public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();//队列满,则等待
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

    private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();
    }



//take 

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await(); //没有元素,则等待
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    private E dequeue() {
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();   //拿出元素后,唤醒其他等待的线程
        return x;
    }

2.3 poll:

   public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }

3. PriorityBlockingQueue:

 

3.1 构造方法:

 private static final int DEFAULT_INITIAL_CAPACITY = 11;
 public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }

3.2 put、add、offer:

    public void put(E e) {
        offer(e); // never need to block
    }
    public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        final ReentrantLock lock = this.lock;
        lock.lock();
        int n, cap;
        Object[] array;
        while ((n = size) >= (cap = (array = queue).length))
            tryGrow(array, cap); //当队列满时,进行扩容
        try {
            Comparator<? super E> cmp = comparator;
            if (cmp == null)
                siftUpComparable(n, e, array); //排序
            else
                siftUpUsingComparator(n, e, array, cmp);
            size = n + 1;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
        return true;
    }

4. SynchronousQueue :

 

4.1 构造方法:

    public SynchronousQueue() {
        this(false);
    }

    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }


  
    public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        if (transferer.transfer(e, false, 0) == null) {
            Thread.interrupted();
            throw new InterruptedException();
        }
    }

4.2 put or take: 

 根据e的元素是否为null判断

 E transfer(E e, boolean timed, long nanos) {
SNode s = null; // constructed/reused as needed
            int mode = (e == null) ? REQUEST : DATA;

            for (;;) {
                SNode h = head; //栈顶元素
                if (h == null || h.mode == mode) {  // empty or same-mode
                    //有超时且已到期
                    if (timed && nanos <= 0) {      // can't wait
                         //头节点不为空且是取消状态
                        if (h != null && h.isCancelled())
                            //弹出头节点,并进入下一个循环
                            casHead(h, h.next);     // pop cancelled node
                        else
                            return null;
                    } else if (casHead(h, s = snode(s, e, h, mode))) {//入栈成功
                           // 调用awaitFulfill()方法自旋+阻塞当前入栈的线程并等待被匹配到
                        SNode m = awaitFulfill(s, timed, nanos);
                        if (m == s) {               // wait was cancelled
                            clean(s); 
                            return null;
                        }
                        // 如果头节点不为空,并且头节点的下一个节点是s;把h和s都弹出
                        if ((h = head) != null && h.next == s)
                            casHead(h, s.next);     // help s's fulfiller
                            // 根据当前节点的模式判断返回m还是s中的值
                        return (E) ((mode == REQUEST) ? m.item : s.item);
                    }
                } else if (!isFulfilling(h.mode)) { // try to fulfill
                    if (h.isCancelled())            // 如果头节点已经取消了,就把它弹出栈
                        casHead(h, h.next);         
                    else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
                        for (;;) { // loop until matched or waiters disappear
                            SNode m = s.next;       // m is s's match  如果m为null,说明除了s节点外的节点都被其它线程先一步匹配掉了
                            if (m == null) {        // all waiters are gone
                                casHead(s, null);   // pop fulfill node
                                s = null;           // use new node next time
                                break;              // restart main loop
                            }
                            SNode mn = m.next;
                            if (m.tryMatch(s)) {
                                casHead(s, mn);     // pop both s and m
                                return (E) ((mode == REQUEST) ? m.item : s.item);
                            } else                  // lost match
                                s.casNext(m, mn);   // help unlink
                        }
                    }
                } else {                            // help a fulfiller
                    SNode m = h.next;               // m is h's match
                    if (m == null)                  // waiter is gone
                        casHead(h, null);           // pop fulfilling node
                    else {
                        SNode mn = m.next;
                        if (m.tryMatch(h))          // help match
                            casHead(h, mn);         // pop both h and m
                        else                        // lost match
                            h.casNext(m, mn);       // help unlink
                    }
                }
            }
        }


        SNode awaitFulfill(SNode s, boolean timed, long nanos) {
  // 到期时间
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
   // 当前线程
            Thread w = Thread.currentThread();
    // 自旋次数
            int spins = (shouldSpin(s) ?
                         (timed ? maxTimedSpins : maxUntimedSpins) : 0);
            for (;;) {
                if (w.isInterrupted())//当前线程中断,清除
                    s.tryCancel();
                SNode m = s.match;
                if (m != null)//匹配到了
                    return m;
                if (timed) { //需要超时处理
                    nanos = deadline - System.nanoTime();
                    if (nanos <= 0L) {//超时
                        s.tryCancel();
                        continue;
                    }
                }
                if (spins > 0)//还有自旋次数
                    spins = shouldSpin(s) ? (spins-1) : 0;
                else if (s.waiter == null)
                    s.waiter = w; // establish waiter so can park next iter
                else if (!timed)
                    LockSupport.park(this);
                else if (nanos > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanos);
            }
        }

4.3 注意:

1.两种创建模式,公平方式(队列),非公平方式(栈)(默认)。
2.栈的节点有三种模式:生产者,消费者,匹配中。
3.无缓存队列,用于两个线程直接移交元素,一般用于生产和消费相当的场景

5.DelayQueue:

5.1 put && take && peek:


///put
    public void put(E e) {
        offer(e);
    }
    public boolean offer(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            q.offer(e);
            if (q.peek() == e) {
                leader = null;
                available.signal();
            }
            return true;
        } finally {
            lock.unlock();
        }
    }

//take
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                E first = q.peek();  //查询第一个
                if (first == null)
                    available.await(); //无元素,需要等待
                else {
                    long delay = first.getDelay(NANOSECONDS); //等待时间
                    if (delay <= 0)
                        return q.poll(); //拿出元素
                    first = null; // don't retain ref while waiting将第一个置为null
                    if (leader != null)
                        available.await();//线程等待
                    else {
                        Thread thisThread = Thread.currentThread();
                        leader = thisThread;
                        try {
                            available.awaitNanos(delay);//线程等待指定时间
                        } finally {
                            if (leader == thisThread)
                                leader = null;
                        }
                    }
                }
            }
        } finally {
            if (leader == null && q.peek() != null)
                available.signal();
            lock.unlock();
        }
    }


//peek 查询,不等待,直接返回
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return q.peek();
        } finally {
            lock.unlock();
        }
    }

LinkedTransferQueue:

实现TransferQueue接口

6.1 put && take:

//put && take

    public void put(E e) {
        xfer(e, true, ASYNC, 0);
    }
    public E take() throws InterruptedException {
        E e = xfer(null, false, SYNC, 0);
        if (e != null)
            return e;
        Thread.interrupted();
        throw new InterruptedException();
    }

    private E xfer(E e, boolean haveData, int how, long nanos) {
        if (haveData && (e == null))//put请求且e为null
            throw new NullPointerException();
        Node s = null;                        // the node to append, if needed

        retry:
        for (;;) {                            // restart on append race

            for (Node h = head, p = h; p != null;) { // find & match first node
                boolean isData = p.isData;
                Object item = p.item;
                if (item != p && (item != null) == isData) { // unmatched
                    if (isData == haveData)   // can't match 操作和节点类型不匹配,跳出内循环
                        break;
                    if (p.casItem(item, e)) { // match 操作和节点类型匹配
                        for (Node q = p; q != h;) {
                            Node n = q.next;  // update by 2 unless singleton
                            if (head == h && casHead(h, n == null ? q : n)) {//设置新的head节点
                                h.forgetNext();//将旧的节点自连接,方便GC回收
                                break;跳出内循环
                            }                 // advance and retry
                            if ((h = head)   == null ||
                                (q = h.next) == null || !q.isMatched())
                                break;        // unless slack < 2
                        }
                        LockSupport.unpark(p.waiter);//匹配成功,唤醒阻塞线程
                        return LinkedTransferQueue.<E>cast(item);
                    }
                }
                //当前节点匹配完,寻找下一个节点
                Node n = p.next;
                p = (p != n) ? n : (h = head); // 当前节点已经离队,从head开始寻找
            }
            //整个队列都没匹配到
            if (how != NOW) {                 // No matches available
                if (s == null)
                    s = new Node(e, haveData);
                //将s添加队尾,并返回s的前继节点
                Node pred = tryAppend(s, haveData);
                if (pred == null)//前继节点为Null,说明有线程竞争;则从retry开始
                    continue retry;           // lost race vs opposite mode
                if (how != ASYNC)//同步阻塞;;直到该节点被匹配或者取消
                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
            }
            return e; // not waiting
        }
    }

6.2 注意:

LinkedTransferQueue实际上是一种预占模式:


消费线程获取元素,如果队列为空,则生成一个节点(节点元素为null)入队,消费者等待在这个节点上;

生产者线程发现有一个null的节点,它生产的元素不入队,直接填充到该节点上,并唤醒消费者去消费。若生产者找不到元素为null的节点,则直接入队。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值