ArrayBlockingQueue (ArrayBlockingQueue) ArrayBlockingQueue (ArrayBlockingQueue)
LinkedBlockingQueue summary
LinkedBlockingQueue has the following features:
1. He realizes data storage with linked lists at the bottom;
2. It is a FIFO unbounded blocking queue. Maximum data Length Default Intenger Maximum Integer.MAX_VALUE The length can also be set.
Introduction to Important Attributes
The main attributes are shown below:
LinkedBlockingQueue has an inner class Node that makes up its list of data stores. The Node’s item data stores the data, next represents the next Node, and next is null for the trailing Node.
Capacity Indicates the maximum amount of data that can be stored in a queue. The value is set during initialization. The default value is integer. MAX_VALUE.
Count represents the amount of data currently stored and is of type AtomicInteger (why?). ;
Head The head node of a list whose item holds no data;
Tail The tail node of the list. Its next is null, i.e. there is no next node.
TakeLock and notEmpty control the blocking of take methods;
PutLock and notFull control the blocking of put methods;
LinkedBlockingQueue uses two locks to control read and write data. Separate read and write operations can exist simultaneously, so count can be modified by multiple threads.
The two most critical private methods
There are also two key methods for LinkedBlockingQueue, as shown below:
The enqueue and dequeue methods of LinkedBlockingQueue are simpler than those of ArrayBlockingQueue;
The enqueue method puts the new node in the next of last and sets the node as the last node.
The dequeue takes the first next node as the first node, and then the previous first node sets itself as next, leaving the list, and the next GC will be recycled.
First is then used as head and is set to null after the item is taken out, so the head node does not store data and is upgraded by the next node.
The two methods of LinkedBlockingQueue are relatively simple, but you can also see that it implements FIFO FIFO.
Introduction of main methods
LinkedBlockingQueue and ArrayBlockingQueue both derive from AbstractQueue and implement the BlockingQueue interface, so they all provide similar methods, similar functionality, and different implementations, as described in the previous article. Just look at the implementation of the take and put methods.
The put method looks like this:
There are four steps:
Encapsulate data as Node Node, get put lock;
Verify that the queue is full; if the queue is full, the thread is blocked.
If not, the node is added to the queue, count is incremented by 1, and the number before that is added is obtained.
Wake up the blocked PUT thread if the number is still less than the maximum, and wake up the take thread if the number was zero.
Take method:
The take method is similar to the put method, consisting of the following four steps:
First get the take lock;
Determine if there is data in the queue, if not, block the thread;
Call the dequeue method to get the data and subtract count by 1;
If the number of queues before fetching is greater than 1, there is data available and other take threads can be woken up. If the number of queues before fetching is equal to the maximum number of containers, there may be blocked PUT threads that need to be woken up.
As you can see, the put and take methods are very simple. They first acquire the lock, then determine whether to block according to the number of queues, then add or acquire data, and finally wake up the corresponding thread.
Compare to ArrayBlockingQueue (emphasis)
LinkedBlockingQueue and ArrayBlockingQueue are very similar classes and can be compared to show their strengths and weaknesses. The main comparisons are as follows:
The underlying implementation of LinkedBlockingQueue is a linked list, and ArrayBlockingQueue is an array. ArrayBlockingQueue initialization requires an array, while LinkedBlockingQueue is a dynamic number of Node objects; So ArrayBlockingQueue requires pre-allocated memory, whereas LinkedBlockingQueue does not. If you expect to cache a lot of data, ArrayBlockingQueue needs a large chunk to start with.
But ArrayBlockingQueue is faster to add elements because it just wants to put the reference to the object to be saved in the array, whereas LinkedBlockingQueue needs to create a Node object; At the same time, the Node object becomes garbage after the acquisition. There will be a lot of garbage in the case of large read and write, which may affect the performance of the program.
ArrayBlockingQueue uses one lock to control reads and writes, and LinkedBlockingQueue uses two locks to control reads and writes. Because ArrayBlockingQueue doesn’t have to worry about overwriting data, LinkedBlockingQueue doesn’t have to worry about that and can support both reads and writes, and ArrayBlockingQueue supports one operation at a time, So LinkedBlockingQueue throughput is higher.
ArrayBlockingQueue takes up a fixed amount of memory, so it cannot support a large cache, but has a lower latency per operation, whereas LinkedBlockingQueue does not temporarily use an initialized memory, but consumes more memory per operation, but also supports reads and writes so it has a higher throughput.
However, when using LinkedBlockingQueue, if the default size is used and the production rate is greater than the consumption rate, it is possible to run out of memory.
conclusion
LinkedBlockingQueue and ArrayBlockingQueue provide exactly the same functionality, but their underlying implementation is different, so the focus is different and can be used as appropriate.
Java programmer daily study notes, such as understanding the wrong welcome to exchange discussion!