How far can we go? series (42)
Nonsense:
Take the time, read some juc the source of learning. Follow the Juc roughly aside, after all, will definitely come again.
Theme:
What's a blockingqueue?
java.util.QueueThat's additionally supports operations that wait for the queue to become non-empty when retrieving a element, and wait for Space to become available in the queue when storing an element. Block of a blocked queue at two operation queues: 1, when an element in the queue is fetched, the queue is empty, blocking until there are elements in the queue. 2, when a single element is stored, the queue is full, blocking until there is an empty position in the queue to store. Blockingqueue the rules of implementation as an interface.here are the 4 types of access operation methods for the queue core:
| & nbsp; |
Throws exception |
special value |
Blocks |
times out |
| Insert |
Add (E) |
offer (e) |
PU T (e) |
offer (e, time, unit) |
| Remove |
Code>remove () |
poll () |
take () |
poll (time, unit) |
| examine |
Element () |
Peek () |
Not applicable |
Not applicable |
according to the table above, the policy of the queue full or empty contains, throws an exception, returns a Boolean value, blocks the thread, and blocks to a timeout. It's not clear why you should choose this. What we need to note is that except for the third, none of the other methods really block threads.
Arrayblockingqueue:A queue that is implemented internally with an array, in accordance with the element first-out (FIFO) principle. After initialization, the capacity of the queue cannot be changed. An optional fairness mechanism is supported to ensure that the blocked operating threads can wait in sequence. The default is an unfair mechanism.
Source code implementation:1, use an array of object[] to store elements
//container where the queue holds elementsFinalobject[] items;//next Read or remove locationintTakeindex;//Place the next placed elementintPutindex;//number of valid elements in the queueintcount;//protection lock for all accessFinalReentrantlock lock;//conditions to wait for acquisitionPrivate FinalCondition Notempty;//conditions for waiting to be putPrivate FinalCondition Notfull;
2, the entire queue has a wrapping mechanism, such as this time I have been fetching data, then read the next bidding clubs has been moved back, know the end of the array. If this is the end of the array, the header of the array is followed by a subscript. This is the realization of a queue that wraps around. This is a very subtle implementation of the entire queue implementation of the basic mechanism.
In this way, the capacity of this queue cannot be changed.
// Pointer move forward Final Int Inc (int i) { return (++i = = items.length)? 0 : I;} // pointer moves back Final int Dec (int i) { return ((i = = 0) items.length:i)-1;}
3, directly look at the core of the put and take method implementation:
Put
Public voidPut (e e)throwsinterruptedexception {checknotnull (e);//cannot put null FinalReentrantlock lock = This. Lock;//assign the lock to the final modified local variable first//in many classes of JUC, you will see this notation: Assigning a property of a class to the method within a final modifier of a variable. //this is because the properties of the class are stored in the heap, and the variables inside the method are stored on the method stack, and the access method stack is faster than accessing the heap. //here, the This.lock property is accessed two times, and by assigning a value to the local variable of the method, the access to the heap is saved. //other class properties are only accessed once and do not need to be handled this way. Lock.lockinterruptibly ();//Locking Try { //loop guarantees avoid false wake-up, false wakeup is the case if there are multiple threads that wait,
While being awakened at the same time will execute the following insert//if in the while loop, then the count size is determined before waking to determine whether to continue wait or insert. while(Count = =items.length) notfull.await ();//Blocking ThreadsInsert (e); } finally{lock.unlock ();//Release Lock } }
Take
Public throws interruptedexception { finalthis. Lock; Lock.lockinterruptibly (); Try { while (count = = 0) notempty.await () ; return extract (); finally { lock.unlock (); } }
Using the Insert and extract methods, it is also possible to see that only those methods are invoked if the lock is held, so that the call to this method does not require a relationship whether it is thread safe or not, so that thread safety is guaranteed before the call:
private void insert (E x) {Items[putindex] = x; // 1, save value, very simple putindex = Inc (PUTINDEX); // 2, move subscript, use the Inc method ++count; //3, increase the total number of elements notempty.signal (); //4, Notifies the read thread waiting on a non-empty condition }
Private E Extract () { finalthis. Items; the class variable is first assigned to the method variable, which is mentioned earlier in this .<e>cast (Items[takeindex] ); NULL ; = Inc (TAKEINDEX); --count; Notfull.signal (); return x; }
Operation:
1, an array of rings
2, put one more element:
3. Take an Element
Of course, there are other methods in Arrayblockingqueue, here do not repeat. Interested students can go deep into the exploration.
Summarize:
1, the array design of a ring is very ingenious.
2, assigning a class variable to the encoding of the method variable
Let's move on
----------------------------------------------------------------------
Effort is not necessarily successful, but not effort will not succeed.
arrayblockingqueue-How far can we go? series (42)