`
longzhun
  • 浏览: 370031 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

阻塞队列之LinkedBlockingQueue 源码

 
阅读更多

 

 

package java.util.concurrent;

import java.util.concurrent.atomic.*;

import java.util.concurrent.locks.*;

import java.util.*;

 

 * @since 1.5

 * @author Doug Lea

 * @param <E> the type of elements held in this collection

 *

 */

public class LinkedBlockingQueue<E> extends AbstractQueue<E>

        implements BlockingQueue<E>, java.io.Serializable {

    private static final long serialVersionUID = -6903933977591709194L;

 

 

 

    /**

     * Linked list node class

     */

    static class Node<E> {

        E item;

        /**

         * One of:

         * - the real successor Node

         * - this Node, meaning the successor is head.next

         * - null, meaning there is no successor (this is the last node)

         */

 

        Node<E> next;

        Node(E x) { item = x; }

    }

 

    /** The capacity bound, or Integer.MAX_VALUE if none */

    private final int capacity;

 

    /** Current number of elements */

    private final AtomicInteger count = new AtomicInteger(0);

 

    /** Head of linked list */

    private transient Node<E> head;

 

    /** Tail of linked list */

    private transient Node<E> last;

 

    /** Lock held by take, poll, etc */

    private final ReentrantLock takeLock = new ReentrantLock();

 

    /** Wait queue for waiting takes */

    private final Condition notEmpty = takeLock.newCondition();

 

    /** Lock held by put, offer, etc */

    private final ReentrantLock putLock = new ReentrantLock();

 

    /** Wait queue for waiting puts */

    private final Condition notFull = putLock.newCondition();

 

    /**

     * Signals a waiting take. Called only from put/offer (which do not

     * otherwise ordinarily lock takeLock.)

     */

    private void signalNotEmpty() {

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lock();

        try {

            notEmpty.signal();

        } finally {

            takeLock.unlock();

        }

    }

 

    /**

     * Signals a waiting put. Called only from take/poll.

     */

    private void signalNotFull() {

        final ReentrantLock putLock = this.putLock;

        putLock.lock();

        try {

            notFull.signal();

        } finally {

            putLock.unlock();

        }

    }

 

    /**

     * 创建一个节点并将其链接队列的末端.

     * @param x the item

     */

    private void enqueue(E x) {

        // assert putLock.isHeldByCurrentThread();

        last = last.next = new Node<E>(x);

    }

 

    /**

     * 队列的顶端删除一个节点

     * @return the node

     */

    private E dequeue() {

        // assert takeLock.isHeldByCurrentThread();

        Node<E> h = head;

        Node<E> first = h.next;

        h.next = h; // help GC

        head = first;

        E x = first.item;

        first.item = null;

        return x;

    }

 

    /**

     * puts and takes 加锁.

     */

    void fullyLock() {

        putLock.lock();

        takeLock.lock();

    }

 

    /**

     * puts and takes.解锁

     */

    void fullyUnlock() {

        takeLock.unlock();

        putLock.unlock();

    }

 

    /**

     * 当前线程是否持有两个锁

     */

    boolean isFullyLocked() {

        return (putLock.isHeldByCurrentThread() &&

                takeLock.isHeldByCurrentThread());

    }

 

 

    /**

     * 创建一个LinkedBlockingQueue容量为Integer.MAX_VALUE

     * 

     */

    public LinkedBlockingQueue() {

        this(Integer.MAX_VALUE);

    }

 

    /**

     * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.

     *

     * @param capacity the capacity of this queue

     * @throws IllegalArgumentException if <tt>capacity</tt> is not greater

     *         than zero

     */

    public LinkedBlockingQueue(int capacity) {

        if (capacity <= 0) throw new IllegalArgumentException();

        this.capacity = capacity;

        last = head = new Node<E>(null);

    }

 

    /**

     * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of

     * {@link Integer#MAX_VALUE}, initially containing the elements of the

     * given collection,

     * added in traversal order of the collection's iterator.

     *

     * @param c the collection of elements to initially contain

     * @throws NullPointerException if the specified collection or any

     *         of its elements are null

     */

    public LinkedBlockingQueue(Collection<? extends E> c) {

        this(Integer.MAX_VALUE);

        final ReentrantLock putLock = this.putLock;

        putLock.lock(); // Never contended, but necessary for visibility

        try {

            int n = 0;

            for (E e : c) {

                if (e == null)

                    throw new NullPointerException();

                if (n == capacity)

                    throw new IllegalStateException("Queue full");

                enqueue(e);

                ++n;

            }

            count.set(n);

        } finally {

            putLock.unlock();

        }

    }

 

 

    // this doc comment is overridden to remove the reference to collections

    // greater in size than Integer.MAX_VALUE

    /**

     * Returns the number of elements in this queue.

     *

     * @return the number of elements in this queue

     */

    public int size() {

        return count.get();

    }

 

    // this doc comment is a modified copy of the inherited doc comment,

    // without the reference to unlimited queues.

    /**

     * Returns the number of additional elements that this queue can ideally

     * (in the absence of memory or resource constraints) accept without

     * blocking. This is always equal to the initial capacity of this queue

     * less the current <tt>size</tt> of this queue.

     *

     * <p>Note that you <em>cannot</em> always tell if an attempt to insert

     * an element will succeed by inspecting <tt>remainingCapacity</tt>

     * because it may be the case that another thread is about to

     * insert or remove an element.

     */

    public int remainingCapacity() {

        return capacity - count.get();

    }

 

    /**

     * Inserts the specified element at the tail of this queue, waiting if

     * necessary for space to become available.

     *

     * @throws InterruptedException {@inheritDoc}

     * @throws NullPointerException {@inheritDoc}

     */

    public void put(E e) throws InterruptedException {

        if (e == null) throw new NullPointerException();

        // Note: convention in all put/take/etc is to preset local var

        // holding count negative to indicate failure unless set.

        int c = -1;

        final ReentrantLock putLock = this.putLock;

        final AtomicInteger count = this.count;

        putLock.lockInterruptibly();

        try {

            /*

             * Note that count is used in wait guard even though it is

             * not protected by lock. This works because count can

             * only decrease at this point (all other puts are shut

             * out by lock), and we (or some other waiting put) are

             * signalled if it ever changes from

             * capacity. Similarly for all other uses of count in

             * other wait guards.

             */

            while (count.get() == capacity) { 

                    notFull.await();

            }

            enqueue(e);

            c = count.getAndIncrement();

            if (c + 1 < capacity)

                notFull.signal();

        } finally {

            putLock.unlock();

        }

        if (c == 0)

            signalNotEmpty();

    }

 

    /**

     * Inserts the specified element at the tail of this queue, waiting if

     * necessary up to the specified wait time for space to become available.

     *

     * @return <tt>true</tt> if successful, or <tt>false</tt> if

     *         the specified waiting time elapses before space is available.

     * @throws InterruptedException {@inheritDoc}

     * @throws NullPointerException {@inheritDoc}

     */

    public boolean offer(E e, long timeout, TimeUnit unit)

        throws InterruptedException {

 

        if (e == null) throw new NullPointerException();

        long nanos = unit.toNanos(timeout);

        int c = -1;

        final ReentrantLock putLock = this.putLock;

        final AtomicInteger count = this.count;

        putLock.lockInterruptibly();

        try {

            while (count.get() == capacity) {

 

                if (nanos <= 0)

                    return false;

                nanos = notFull.awaitNanos(nanos);

            }

            enqueue(e);

            c = count.getAndIncrement();

           if (c + 1 < capacity)

               notFull.signal();

        } finally {

            putLock.unlock();

        }

        if (c == 0)

            signalNotEmpty();

        return true;

    }

 

    /**

     * Inserts the specified element at the tail of this queue if it is

     * possible to do so immediately without exceeding the queue's capacity,

     * returning <tt>true</tt> upon success and <tt>false</tt> if this queue

     * is full.

     * When using a capacity-restricted queue, this method is generally

     * preferable to method {@link BlockingQueue#add add}, which can fail to

     * insert an element only by throwing an exception.

     *

     * @throws NullPointerException if the specified element is null

     */

    public boolean offer(E e) {

        if (e == null) throw new NullPointerException();

        final AtomicInteger count = this.count;

        if (count.get() == capacity)

            return false;

        int c = -1;

        final ReentrantLock putLock = this.putLock;

        putLock.lock();

        try {

            if (count.get() < capacity) {

                enqueue(e);

                c = count.getAndIncrement();

                if (c + 1 < capacity)

                    notFull.signal();

            }

        } finally {

            putLock.unlock();

        }

        if (c == 0)

            signalNotEmpty();

        return c >= 0;

    }

 

 

    public E take() throws InterruptedException {

        E x;

        int c = -1;

        final AtomicInteger count = this.count;

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lockInterruptibly();

        try {

                while (count.get() == 0) {

                    notEmpty.await();

                }

            x = dequeue();

            c = count.getAndDecrement();

            if (c > 1)

                notEmpty.signal();

        } finally {

            takeLock.unlock();

        }

        if (c == capacity)

            signalNotFull();

        return x;

    }

 

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {

        E x = null;

        int c = -1;

        long nanos = unit.toNanos(timeout);

        final AtomicInteger count = this.count;

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lockInterruptibly();

        try {

                while (count.get() == 0) { 

                  if (nanos <= 0)

                    return null;

                  nanos = notEmpty.awaitNanos(nanos);

                }

                x = dequeue();

                c = count.getAndDecrement();

                if (c > 1)

                    notEmpty.signal();

        } finally {

            takeLock.unlock();

        }

        if (c == capacity)

            signalNotFull();

        return x;

    }

 

    public E poll() {

        final AtomicInteger count = this.count;

        if (count.get() == 0)

            return null;

        E x = null;

        int c = -1;

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lock();

        try {

            if (count.get() > 0) {

                x = dequeue();

                c = count.getAndDecrement();

                if (c > 1)

                    notEmpty.signal();

            }

        } finally {

            takeLock.unlock();

        }

        if (c == capacity)

            signalNotFull();

        return x;

    }

 

 

    public E peek() {

        if (count.get() == 0)

            return null;

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lock();

        try {

            Node<E> first = head.next;

            if (first == null)

                return null;

            else

                return first.item;

        } finally {

            takeLock.unlock();

        }

    }

 

    /*

     * Unlinks interior Node p with predecessor trail.

     */

    void unlink(Node<E> p, Node<E> trail) {

        // assert isFullyLocked();

        // p.next is not changed, to allow iterators that are

        // traversing p to maintain their weak-consistency guarantee.

        p.item = null;

        trail.next = p.next;

        if (last == p)

            last = trail;

        if (count.getAndDecrement() == capacity)

            notFull.signal();

    }

 

    /**

     * Removes a single instance of the specified element from this queue,

     * if it is present.  More formally, removes an element <tt>e</tt> such

     * that <tt>o.equals(e)</tt>, if this queue contains one or more such

     * elements.

     * Returns <tt>true</tt> if this queue contained the specified element

     * (or equivalently, if this queue changed as a result of the call).

     *

     * @param o element to be removed from this queue, if present

     * @return <tt>true</tt> if this queue changed as a result of the call

     */

    public boolean remove(Object o) {

        if (o == null) return false;

        fullyLock();

        try {

            for (Node<E> trail = head, p = trail.next;

                 p != null;

                 trail = p, p = p.next) {

                if (o.equals(p.item)) {

                    unlink(p, trail);

                    return true;

                }

            }

            return false;

        } finally {

            fullyUnlock();

        }

    }

 

    /**

     * Returns an array containing all of the elements in this queue, in

     * proper sequence.

     *

     * <p>The returned array will be "safe" in that no references to it are

     * maintained by this queue.  (In other words, this method must allocate

     * a new array).  The caller is thus free to modify the returned array.

     *

     * <p>This method acts as bridge between array-based and collection-based

     * APIs.

     *

     * @return an array containing all of the elements in this queue

     */

    public Object[] toArray() {

        fullyLock();

        try {

            int size = count.get();

            Object[] a = new Object[size];

            int k = 0;

            for (Node<E> p = head.next; p != null; p = p.next)

                a[k++] = p.item;

            return a;

        } finally {

            fullyUnlock();

        }

    }

 

    /**

     * Returns an array containing all of the elements in this queue, in

     * proper sequence; the runtime type of the returned array is that of

     * the specified array.  If the queue fits in the specified array, it

     * is returned therein.  Otherwise, a new array is allocated with the

     * runtime type of the specified array and the size of this queue.

     *

     * <p>If this queue fits in the specified array with room to spare

     * (i.e., the array has more elements than this queue), the element in

     * the array immediately following the end of the queue is set to

     * <tt>null</tt>.

     *

     * <p>Like the {@link #toArray()} method, this method acts as bridge between

     * array-based and collection-based APIs.  Further, this method allows

     * precise control over the runtime type of the output array, and may,

     * under certain circumstances, be used to save allocation costs.

     *

     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.

     * The following code can be used to dump the queue into a newly

     * allocated array of <tt>String</tt>:

     *

     * <pre>

     *     String[] y = x.toArray(new String[0]);</pre>

     *

     * Note that <tt>toArray(new Object[0])</tt> is identical in function to

     * <tt>toArray()</tt>.

     *

     * @param a the array into which the elements of the queue are to

     *          be stored, if it is big enough; otherwise, a new array of the

     *          same runtime type is allocated for this purpose

     * @return an array containing all of the elements in this queue

     * @throws ArrayStoreException if the runtime type of the specified array

     *         is not a supertype of the runtime type of every element in

     *         this queue

     * @throws NullPointerException if the specified array is null

     */

    // @SuppressWarnings("unchecked")

    public <T> T[] toArray(T[] a) {

        fullyLock();

        try {

            int size = count.get();

            if (a.length < size)

                a = (T[])java.lang.reflect.Array.newInstance

                    (a.getClass().getComponentType(), size);

 

            int k = 0;

            for (Node<E> p = head.next; p != null; p = p.next)

                a[k++] = (T)p.item;

            if (a.length > k)

                a[k] = null;

            return a;

        } finally {

            fullyUnlock();

        }

    }

 

    public String toString() {

        fullyLock();

        try {

            return super.toString();

        } finally {

            fullyUnlock();

        }

    }

 

    /**

     * Atomically removes all of the elements from this queue.

     * The queue will be empty after this call returns.

     */

    public void clear() {

        fullyLock();

        try {

            for (Node<E> p, h = head; (p = h.next) != null; h = p) {

                h.next = h;

                p.item = null;

            }

            head = last;

            // assert head.item == null && head.next == null;

            if (count.getAndSet(0) == capacity)

                notFull.signal();

        } finally {

            fullyUnlock();

        }

    }

 

    /**

     * @throws UnsupportedOperationException {@inheritDoc}

     * @throws ClassCastException            {@inheritDoc}

     * @throws NullPointerException          {@inheritDoc}

     * @throws IllegalArgumentException      {@inheritDoc}

     */

    public int drainTo(Collection<? super E> c) {

        return drainTo(c, Integer.MAX_VALUE);

 

    }

 

    /**

     * @throws UnsupportedOperationException {@inheritDoc}

     * @throws ClassCastException            {@inheritDoc}

     * @throws NullPointerException          {@inheritDoc}

     * @throws IllegalArgumentException      {@inheritDoc}

     */

    public int drainTo(Collection<? super E> c, int maxElements) {

        if (c == null)

            throw new NullPointerException();

        if (c == this)

            throw new IllegalArgumentException();

        boolean signalNotFull = false;

        final ReentrantLock takeLock = this.takeLock;

        takeLock.lock();

        try {

            int n = Math.min(maxElements, count.get());

            Node<E> h = head;

            int i = 0;

            try {

                while (i < n) {

                    Node<E> p = h.next;

                    c.add(p.item);

                    p.item = null;

                    h.next = h;

                    h = p;

                    ++i;

                }

                return n;

            } finally {

                // Restore invariants even if c.add() threw

                if (i > 0) {

                    // assert h.item == null;

                    head = h;

                    signalNotFull = (count.getAndAdd(-i) == capacity);

                }

            }

        } finally {

            takeLock.unlock();

            if (signalNotFull)

                 signalNotFull();

        }

    }

 

    /**

     * Returns an iterator over the elements in this queue in proper sequence.

     * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that

     * will never throw {@link ConcurrentModificationException},

     * and guarantees to traverse elements as they existed upon

     * construction of the iterator, and may (but is not guaranteed to)

     * reflect any modifications subsequent to construction.

     *

     * @return an iterator over the elements in this queue in proper sequence

     */

    public Iterator<E> iterator() {

      return new Itr();

    }

 

    private class Itr implements Iterator<E> {

        /*

         * Basic weakly-consistent iterator.  At all times hold the next

         * item to hand out so that if hasNext() reports true, we will

         * still have it to return even if lost race with a take etc.

         */

        private Node<E> current;

        private Node<E> lastRet;

        private E currentElement;

 

        Itr() {

            fullyLock();

            try {

                current = head.next;

                if (current != null)

                    currentElement = current.item;

            } finally {

               fullyUnlock();

            }

        }

 

        public boolean hasNext() {

            return current != null;

        }

 

        /**

         * Returns the next live successor of p, or null if no such.

         *  

         * Unlike other traversal methods, iterators need to handle both:

         * - dequeued nodes (p.next == p)

         * -  (possibly multiple) interior removed nodes (p.item == null)

         */

        private Node<E> nextNode(Node<E> p) {

            for (; ;) {   

                Node s = p.next;

                if (s == p)

                   return head.next;

                if (s == null || s.item != null)

                   return s;

                p = s;

            }

        }

 

        public E next() {

            fullyLock();

            try {

                if (current == null)

                    throw new NoSuchElementException();

                E x = currentElement;

                lastRet = current;

                current = nextNode(current);

                currentElement = (current == null) ? null : current.item;

                return x;

            } finally {

               fullyUnlock();

            }

        }

 

        public void remove() {

            if (lastRet == null)

                throw new IllegalStateException();

            fullyLock();

            try {

                Node<E> node = lastRet;

                lastRet = null;

                for (Node<E> trail = head, p = trail.next;

                     p != null;

                     trail = p, p = p.next) {

                     if (p == node) {

                         unlink(p, trail);

                         break;

                      }

               }

            } finally {

                fullyUnlock();

            }

        }

    }

 

    /**

     * Save the state to a stream (that is, serialize it).

     *

     * @serialData The capacity is emitted (int), followed by all of

     * its elements (each an <tt>Object</tt>) in the proper order,

     * followed by a null

     * @param s the stream

     */

    private void writeObject(java.io.ObjectOutputStream s)

        throws java.io.IOException {

 

        fullyLock();

        try {

            // Write out any hidden stuff, plus capacity

            s.defaultWriteObject();

 

            // Write out all elements in the proper order.

            for (Node<E> p = head.next; p != null; p = p.next)

                s.writeObject(p.item);

 

            // Use trailing null as sentinel

            s.writeObject(null);

        } finally {

            fullyUnlock();

        }

    }

 

    /**

     * Reconstitute this queue instance from a stream (that is,

     * deserialize it).

     * @param s the stream

     */

    private void readObject(java.io.ObjectInputStream s)

        throws java.io.IOException, ClassNotFoundException {

        // Read in capacity, and any hidden stuff

        s.defaultReadObject();

 

        count.set(0);

        last = head = new Node<E>(null);

 

        // Read in all elements and place in queue

        for (;;) {

            // @SuppressWarnings("unchecked")

            E item = (E)s.readObject();

            if (item == null)

                break;

            add(item);

        }

    }

}


 

分享到:
评论

相关推荐

    生产者/消费者模式 阻塞队列 LinkedBlockingQueue

    在Java中,阻塞队列(BlockingQueue)是一个很好的实现生产者/消费者模式的工具,而LinkedBlockingQueue则是Java并发包(java.util.concurrent)中提供的一个具体实现。 LinkedBlockingQueue是一个基于链表结构的...

    元素唯一的LinkedBlockingQueue阻塞队列

    《元素唯一的LinkedBlockingQueue阻塞队列》 在Java并发编程中,`LinkedBlockingQueue`是一种基于链表结构的阻塞队列,它在多线程环境下的性能表现优秀,常用于实现生产者消费者模型。这个队列的一个关键特性是其...

    java队列源码

    其中,`ConcurrentLinkedQueue` 是一个非阻塞的线程安全队列,而 `LinkedBlockingQueue` 是一个阻塞队列,适用于生产者-消费者模型。 2. **线程安全** - 在多线程环境下,线程安全队列是至关重要的,因为它们确保...

    LinkedBlockingQueue + 单向链表基本结构

    总的来说,LinkedBlockingQueue通过单向链表的数据结构,结合阻塞队列的特性,为Java并发编程提供了一种高效的解决方案。了解其内部工作原理有助于我们更好地利用这一工具,优化并发程序的性能和可维护性。在实际...

    java队列

    `LinkedBlockingQueue`和`ArrayBlockingQueue`是两个常见的阻塞队列实现。 3. **并发工具**:Java并发库提供了一些工具类,如`ExecutorService`和`ThreadPoolExecutor`,它们使用队列来管理待执行的任务。这些工具...

    java队列Java系列2021.pdf

    阻塞队列在Java并发包java.util.concurrent中提供了多种实现,如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、DelayQueue和SynchronousQueue等,每种阻塞队列都根据其特性适用于不同的场景。...

    多线程 队列利用

    3. **并发容器**:Java的`java.util.concurrent`包提供了多种并发队列,如`ArrayBlockingQueue`、`LinkedBlockingQueue`和`ConcurrentLinkedQueue`等,它们为多线程环境提供了高效的队列操作。 4. **工作窃取算法**...

    TOMCAT的线程池源码

    TaskQueue通常使用阻塞队列(如LinkedBlockingQueue)实现,它具有很好的性能特性,如线程安全和无锁操作。当队列满时,提交任务的线程会被阻塞,直到队列中有空闲位置。反之,当队列为空时,等待工作的线程会被阻塞...

    java concurrent 精简源码

    Java并发库中实现阻塞队列的主要类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue和DelayQueue等。它们在并发编程中起到缓冲和协调生产者与消费者线程的作用,实现高效的数据交换。 3. **线程...

    工作队列示例

    2. **队列类型选择** - 不同类型的阻塞队列(如ArrayBlockingQueue、LinkedBlockingQueue或SynchronousQueue)有不同的性能特征,需要根据实际需求选择。 3. **拒绝策略配置** - 预先设定合理的拒绝策略,防止系统...

    ArrayBlockingQueue源码分析.docx

    `ArrayBlockingQueue` 是一种高性能的并发队列实现,适合高吞吐量的场景,但相比于其他无界队列(如 `LinkedBlockingQueue`),它的延迟可能会更高。这是因为有界队列需要处理满和空的情况,可能需要线程等待。 7....

    无边界-生成者消费者源码

    生成者消费者模式的核心在于使用了阻塞队列(BlockingQueue)来作为共享资源,这个队列在Java中由`java.util.concurrent`包中的类如`ArrayBlockingQueue`、`LinkedBlockingQueue`等实现。这些队列具有线程安全的特性...

    简单实现BlockingQueue,BlockingQueue源码详解

    2. **LinkedBlockingQueue**:基于链表的阻塞队列,默认无界,也可以设置为有界。插入和删除操作的性能较低,但在高并发环境下,由于其锁粒度较小,整体性能可能优于ArrayBlockingQueue。 3. **...

    Blocking Queue Usage

    在Java中,`java.util.concurrent`包提供了多种阻塞队列的实现,如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue等。每个实现都有其特定的性能特性和使用场景。例如,ArrayBlockingQueue是基于...

    队列(数据结构--Java版)

    此外,对于高效内存管理和大数据处理,还可以了解基于块的队列(BlockQueue)如 `LinkedBlockingQueue` 和 `ArrayBlockingQueue`,它们提供了阻塞操作,适用于生产者-消费者模型。 总结来说,Java中的队列数据结构...

    Queue-Simulation_java_learnvwf_源码.zip

    同时,`BlockingQueue`接口(如`LinkedBlockingQueue`、`ArrayBlockingQueue`等实现)提供了一种线程安全的队列实现,它内置了阻塞操作,使得当队列为空时,尝试获取元素的线程会被阻塞,直到有元素可用。...

    同步java之数组与队列

    在Java编程语言中,数组和队列是两种基础且重要的数据结构。它们在处理数据时起着关键作用,尤其在实现高效算法和并发...通过阅读和分析`Array.java`源码,我们可以进一步理解数组在实现队列时的特定优化和设计决策。

    ArrayBlockingQueue源码解析-动力节点共

    这个队列基于数组实现,支持阻塞插入和移除操作,是线程安全的。在深入理解ArrayBlockingQueue的源码之前,我们需要先了解其基本概念和特性。 ArrayBlockingQueue的核心特点在于其固定大小的容量,这使得它在处理高...

    JAVA经典线程池源码

    - **工作队列**:用来存放等待执行的任务,常见的有无界队列(如`LinkedBlockingQueue`)和有界队列(如`ArrayBlockingQueue`)。 2. **线程池的创建与使用** - 使用`Executors`工厂类创建线程池,如`...

Global site tag (gtag.js) - Google Analytics