ArrayBlockingQueue

 ArrayBlockingQueue

     

public interface BlockingQueue<E> extends Queue<E> {  
     
    /**
	* add element
	*/
    boolean add(E e); //Add the specified element to this queue (if feasible immediately), returning true on success, throwing IllegalStateException otherwise.     
          
    void put(E e) throws InterruptedException; //Add the specified element to this queue, if there is no space available, it will wait (if necessary)  
         
    boolean offer(E e); //Insert the specified element into this queue  
      
	  	  
    /**
	* delete element
	*/   
    
    E take() throws InterruptedException; //Retrieve and remove the head of this queue, if there are no elements in this queue, keep waiting  
         
    E poll(long timeout, TimeUnit unit)  
        throws InterruptedException; // Retrieve and remove the head of this queue, if there are no elements in this queue, wait for the specified waiting time (if necessary)  
                
    boolean remove(Object o); //Remove the specified element from the queue  
		
	E peek();
}  

 

Java code   Favorite code
  1. public class ArrayBlockingQueue<E> extends AbstractQueue<E>  
  2.         implements BlockingQueue<E>, java.io.Serializable {  
  3.   
  4.     private final E[] items;  
  5.       
  6.     /** items index for next take, poll or remove */  
  7.     private int takeIndex;  
  8.       
  9.     /** items index for next put, offer, or add. */  
  10.     private  int  putIndex;  
  11.   
  12.     private int count;  
  13.       
  14.     /*ArrayBlockingQueue shares the same lock object when the producer puts data and the consumer gets data. 
  15.     * This also means that the two cannot really run in parallel, which is especially different from LinkedBlockingQueue 
  16.     */  
  17.     private final ReentrantLock lock;  
  18.   
  19.     private final Condition notEmpty;  
  20.   
  21.     private final Condition notFull;  
  22.       
  23.     ...   
  24. }  

 

/**
 * Constructor
 */
 public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }


    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
			
        this.items = (E[]) new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

 

Java code   Favorite code
  1. final int inc(int i) {  
  2.     return (++i == items.length)? 0 : i;  
  3. }     
  4.   
  5. //The two methods of plugging data and fetching data are mainly referenced inside  
  6.   
  7. //plug data:  
  8. private void insert(E x) {  
  9.     items [putIndex] = x;  
  10.     putIndex = inc (putIndex);  
  11.     ++count;  
  12.     notEmpty.signal();  
  13. }  
  14.   
  15.       
  16. //fetch data:  
  17. private E extract() {  
  18.     final E[] items = this.items;  
  19.     E x = items[takeIndex];  
  20.     items[takeIndex] = null;  
  21.     takeIndex = inc(takeIndex);  
  22.     --count;  
  23.     notFull.signal();  
  24.     return x;  
  25. }  

 put()/take() 可打断,并且会等待

 

 

put()/take() 可打断,并且会等待

/**
* 放数据
*/

public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
		
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            try {
                while (count == items.length)
                    notFull.await();
            } catch (InterruptedException ie) {
                notFull.signal(); // propagate to non-interrupted thread
                throw ie;
            }
            insert(e);
        } finally {
            lock.unlock();
        }
    }
	
	
public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                insert(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

/**
* 取数据
*/

 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            try {
                while (count == 0)
                    notEmpty.await();
            } catch (InterruptedException ie) {
                notEmpty.signal(); // propagate to non-interrupted thread
                throw ie;
            }
            E x = extract();
            return x;
        } finally {
            lock.unlock();
        }
    }
	
	
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == 0)
                return null;
            E x = extract();
            return x;
        } finally {
            lock.unlock();
        }
    }	
	
 public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : items[takeIndex];
        } finally {
            lock.unlock();
        }
    }		
	
public boolean remove(Object o) {
        if (o == null) return false;
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            int i = takeIndex;
            int k = 0;
            for (;;) {
                if (k++ >= count)
                    return false;
                if (o.equals(items[i])) {
                    removeAt(i);
                    return true;
                }
                i = inc(i);
            }

        } finally {
            lock.unlock();
        }
    }

 

从 extract()方法里可见,tabkeIndex维护一个可以提取/移除元素的索引位置,因为takeIndex是从0递增的,所以这个类是FIFO队列

putIndex维护一个可以插入的元素的位置索引。

count显然是维护队列中已经存在的元素总数。

 

ArrayBlockingQueue is a blocking queue in JAVA5, which can customize the queue size. When inserting, if the queue has no free space, the new insert thread will block to the queue. Once the queue has a free space, the blocked thread will execute. Insert . Take data from the queue as: take, put data as: put

 

 

     Array-based blocking queue implementation. Inside ArrayBlockingQueue, a fixed-length array to cache data objects in the queue. This is a commonly used blocking queue. In addition to a fixed-length array, ArrayBlockingQueue also stores two integers. Variables that identify the positions of the head and tail of the queue in the array, respectively.

 

  ArrayBlockingQueue shares the same lock object when the producer puts data and the consumer obtains data, which means that the two cannot really run in parallel, which is especially different from LinkedBlockingQueue ; according to the implementation principle, ArrayBlockingQueue can be used completely. Separating locks, allowing for fully parallel running of producer and consumer operations. The reason why Doug Lea did not do this may be because the data writing and obtaining operations of the ArrayBlockingQueue are light enough that the introduction of an independent locking mechanism, in addition to bringing additional complexity to the code, does not account for the performance at all. to any cheap. Another notable difference between ArrayBlockingQueue and LinkedBlockingQueue is that the former does not generate or destroy any extra object instances when inserting or removing elements, while the latter generates an extra Node object . In a system that needs to process large batches of data efficiently and concurrently for a long time, there is still a certain difference in its impact on GC. When creating an ArrayBlockingQueue, we can also control whether the internal lock of the object adopts a fair lock, and an unfair lock is adopted by default.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326013220&siteId=291194637