The blocking queue (Blockingqueue) is a queue that supports two additional operations. The two additional operations are: When the queue is empty, the thread that gets the element waits for the queue to become non-empty. When the queue is full, the thread that stores the element waits for the queue to be available. Blocking queues are often used for producer and consumer scenarios, where the producer is the thread that adds elements to the queue, and the consumer is the thread that takes the elements from the queue. The blocking queue is the container where the producer stores the elements, and the consumer only takes the elements from the container.
Put a picture first:
Based on the previous description, let's consider the problem that the blocking queue will appear in the program:
Blocking a queue requires two functions: making the thread wait and wake the thread. The details are as follows:
In extreme conditions, you need to suspend the thread, wait for the queue to meet the condition, and then go to the Add or extract operation
After the queue satisfies the condition, the notification thread goes ahead with its pending operation ....
The technology involved:
Thread synchronization and inter-thread communication
Analysis that could generate a deadlock:
At some point, the queue is empty or full, when the producer fails to deposit data or is still in the queue, which results in a queue error
If at this point, the consumer to the queue in the operation will create a deadlock ... A deadlock occurs because the previous producer's actions caused the team to list the problem and did not release the lock
This is to solve the deadlock problem from the point of view of preventing deadlocks.
The first is the synchronization of resources-queue lock, since there is a lock to consider the deadlock problem, and finally the communication between the threads.
In other words, implementing a blocking queue takes into account these three points.
Check the information, mostly Java packaging Good class library, but nothing, anyway, thought, theory are the same, different is to achieve different. But there's a good C # implementation----<< http://www.cnblogs.com/samgk/p/4772806.html C # implements producer consumer queue >>. In fact, the article also said that the blocking queue in the removal of the producer-consumer model of the application, yesterday when the data, Ali Programmer wrote an article about the mail received download, is the use of blocking queue, but I forgot where the original. At that time, I thought of <<c# advanced Programming >> The tenth chapter of the pipeline. The book describes: open a task to read the file name, put in the blocking queue, and then open a queue to read the content according to the file name, the application of the message received the download is the same. Let's not talk about this for the time being, you can go and see the book by yourself.
So how do we implement the blocking queue ourselves? As mentioned above, consider the point, synchronous, thread communication, to prevent deadlocks. Look at the code:
Using system;using system.collections.generic;using system.linq;using system.text;using System.Threading;using System.threading.tasks;namespace suibao.utility{ ///blocking queue (blockingqueue) is a queue that supports two additional operations. The two additional operations are: When the queue is empty, the thread that gets the element waits for the queue to become non-empty. When the queue is full, the thread that stores the element waits for the queue to be available. Blocking queues are often used for producer and consumer scenarios, where the producer is the thread that adds elements to the queue, and the consumer is the thread that takes the elements from the queue. The blocking queue is the container where the producer stores the elements, and the consumer only takes the elements from the container. Blocking a queue requires two functions: making the thread wait and wake the thread. The details are as follows: //in extreme conditions, you need to suspend the thread, wait for the queue to meet the conditions, then go to add or extract operations //wait for the queue to meet the conditions, notify the thread to continue its pending operation .... &NBS p;//technology involved: //thread Synchronization (this instance uses lock) to communicate with threads (this example uses event) ////analysis that could generate deadlocks: //at some point , the queue is empty or full, when the producer fails to deposit data or is still in the queue, which results in a queue error //If, at this point, the consumer will create a deadlock on the queue ... Because the previous producer's operation has caused the team to list the problem and does not release the lock, this will result in deadlocks //This is to resolve the deadlock problem from the standpoint of preventing deadlocks public class blockqueue<t> &NBSP ; { private queue<t> _inner_queue = null; private Manualreseteve NT _dequeue_wait = null; &NBSP; public int Count { get {return _inner_qu Eue. Count; } } public blockqueue (int capacity =-1) { this._inner_queue = capacity =-1? New Queue<t> (): New Queue<t> ( capacity); this._dequeue_wait = new ManualResetEvent (false); } //queue lock public void EnQueue (T item) &N Bsp { if (This._isshutdown = = true) throw new InvalidOperationException ("The service is not open.") EnQueue] "); lock (this._inner_queue) { this._inner_queue. Enqueue (item); &NBSP;THIS._DEQUEUE_wait. Set (); } } //team locking public T DeQueue (int waitTime) { bool _queueempty = false; &nb Sp &NBSP;T item = default (T); while (true) { &NBS P lock (this._inner_queue) { //determine if there are elements in the queue .... if (this._inner_queue. Count > 0) { &N Bsp item = This._inner_queue. Dequeue (); this._dequeue_wait. Reset (); //break; } &N Bsp else { &NBSP ; if (This._isshutdown = true) &N Bsp { &N Bsp throw New InvalidOperationException ("Service not open [DeQueue]."); } &N Bsp else { _queueempty = true; } &N Bsp } } & nbsp &NBSP;IF (item = NULL) { return item; &NBSP,} &NBSP;IF (_queue Empty) { &N Bsp this._dequeue_wait. WaitOne (WaitTime); } } & nbsp;} private bool _isshutdown = false; public void Shutdown () { this._isshutdown = true; This._dequeue_wait. Set (); } public void Clear () { &NB Sp this._inner_queue. Clear (); } }}
So is there a blocking queue in. NET that is encapsulated? Yes, it is! Blockingcollection<> class, in fact, I have written a lot about the thread of the article on this class library, the use of more places. The default container for this class is concurrentqueue, so synchronization is done, and the class implements blocking functionality:
Multiple threads or tasks can add items to the collection at the same time, and if the collection reaches its specified maximum capacity, the manufacturing thread will block until an item in the collection is removed. Multiple users can remove an item at the same time, and if the collection becomes empty, the usage thread will block until the producer adds an item. A manufacturing thread can call completeadding to indicate that an item is no longer added. The consumer monitors the IsCompleted property to see when the collection is empty and no longer adds items.
Original Description BlockingCollection Overview (https://docs.microsoft.com/zh-cn/dotnet/standard/collections/thread-safe/ Blockingcollection-overview)
Feeling a word, Microsoft's good thing is really many, why can't be as easy as Java to be discovered to use?
Yes, we can easily implement a blocking queue with this class, and it's a perfect implementation.
C # Trivia