In concurrent programming we sometimes need to use a thread-safe queue. There are two ways to implement a thread-safe queue: One is to use a blocking algorithm , and the other is to use a non-blocking algorithm .
Queues that use the blocking algorithm can be implemented with a lock (queue and exit with the same lock) or two locks (enqueue and outbound with different locks), where the typical blocking queue is: blockingqueue;
Non-blocking implementations can be implemented using a cyclic CAS approach, and the typical example of a nonblocking queue is concurrentlinkedqueue.
Note: The difference between parallelism and concurrency:
1, parallel means that both do one thing at the same time, such as running, two people are running forward; 2, concurrency refers to the situation of limited resources, the two alternate use of resources, such as a section of the road (single-core CPU resources) at the same time only one person, a after a period, to b,b to continue to a, alternating use, The aim is to improve efficiency.
One, blocking the queue
The common blocking queues are as follows:
Examples of blocking teams and their descriptions are shown in the following table:
Producer-consumer model based on blocking queue
PackageCn.thread;ImportJava.util.concurrent.BlockingQueue;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors;ImportJava.util.concurrent.LinkedBlockingQueue;/*** Multithreaded simulation to implement producer/consumer models*/ Public classBlockingQueueTest2 {/*** * Definition of apple basket **/ Public classBasket {//Basket, capable of accommodating up to 3 applesBlockingqueue<string> Basket =NewLinkedblockingqueue<string> (3); //produce apples, put in baskets Public voidProduce ()throwsinterruptedexception {//Put the method into an apple, if the basket full, until basket have a positionBasket.put ("An apple"); } //consume apples and take them out of the basket PublicString consume ()throwsinterruptedexception {//Take method Take out an apple, if basket is empty, wait until basket has an apple (gets and removes the head of this queue) returnBasket.take (); } } //define Apple producers classProducerImplementsRunnable {PrivateString instance; PrivateBasket Basket; PublicProducer (String instance, basket basket) { This. Instance =instance; This. Basket =Basket; } Public voidrun () {Try { while(true) { //Production of ApplesSystem.out.println ("producer ready to produce apples:" +instance); Basket.produce (); System.out.println ("! Producer production Apple finished:" +instance); //Sleep 300msThread.Sleep (300); } } Catch(Interruptedexception ex) {System.out.println ("Producer interrupted"); } } } //define Apple Consumer classConsumerImplementsRunnable {PrivateString instance; PrivateBasket Basket; PublicConsumer (String instance, basket basket) { This. Instance =instance; This. Basket =Basket; } Public voidrun () {Try { while(true) { //Consumer AppleSYSTEM.OUT.PRINTLN ("Consumer ready to consume Apple:" +instance); System.out.println (Basket.consume ()); System.out.println ("Consumer consumption Apple finished:" +instance); //Sleep 1000msThread.Sleep (1000); } } Catch(Interruptedexception ex) {System.out.println ("Consumer interrupted"); } } } Public Static voidMain (string[] args) {BlockingQueueTest2 test=NewBlockingQueueTest2 (); //build a basket of applesBasket basket = test.NewBasket (); Executorservice Service=Executors.newcachedthreadpool (); Producer Producer= Test.NewProducer ("producer 001", basket); Producer Producer2= Test.NewProducer ("producer 002", basket); Consumer Consumer= Test.NewConsumer ("Consumer 001", basket); Service.submit (producer); Service.submit (PRODUCER2); Service.submit (consumer); }}
Second, the concurrent queue
Concurrentlinkedqueue is a secure implementation of the queue. The elements in the queue are sorted by FIFO principle. The CAS operation is used to ensure the consistency of the elements.
Concurrentlinkedqueue is a link-based, line-free secure queue that uses FIFO rules to sort the nodes, and when we add an element, it is added to the end of the queue, and when we get an element, it returns the element of the queue header. It is implemented using the "Wait-free" algorithm.
Producer-consumer models based on the Concurrentlinkedqueue implementation:
PackageCn.thread;ImportJava.util.concurrent.ConcurrentLinkedQueue;ImportJava.util.concurrent.CountDownLatch;ImportJava.util.concurrent.ExecutorService;Importjava.util.concurrent.Executors; Public classConcurrentlinkedqueuetest {Private Staticconcurrentlinkedqueue<integer> queue =NewConcurrentlinkedqueue<integer>(); Private Static intCount = 2;//Number of Threads//Countdownlatch, a synchronous helper class that allows one or more threads to wait until a set of operations that are performed in another thread is completed. Private StaticCountdownlatch latch =NewCountdownlatch (count); Public Static voidMain (string[] args)throwsinterruptedexception {LongTimestart =System.currenttimemillis (); Executorservice es= Executors.newfixedthreadpool (4); Concurrentlinkedqueuetest.offer (); for(inti = 0; I < count; i++) {Es.submit (NewPoll ()); } latch.await (); //causes the main thread (main) to block until Latch.countdown () is zero to continue executionSystem.out.println ("Cost time" + (System.currenttimemillis ()-Timestart) + "MS"); Es.shutdown (); } /*** Production*/ Public Static voidOffer () { for(inti = 0; I < 100000; i++) {queue.offer (i); } } /*** Consumption **/ Static classPollImplementsRunnable { Public voidrun () {//While (Queue.size () >0) { while(!Queue.isempty ()) {System.out.println (Queue.poll ()); } latch.countdown (); } }}
See also: http://ifeve.com/concurrentlinkedqueue/
Blocking queues and concurrent queues