Producer Consumer Model (1)

Source: Internet
Author: User

  Producer Consumer issues (Producer-consumer problem) is a classic case of multithreaded synchronization issues. The problem describes two threads that share fixed-size buffers-the so-called "producer" and "consumer"-problems that can occur when they actually run. The primary role of the producer is to generate a certain amount of data into the buffer, and then repeat the process. At the same time, consumers consume the data in buffers. The key to this issue is to ensure that producers do not add data when the buffer is full, and consumers do not consume data when the buffer is empty.

What is the producer consumer model
If a producer calls a method of the consumer directly, the producer will have a dependency on the consumer (that is, coupling). In the future, if the consumer's code changes, it may affect the producers.
The producer-consumer model solves the problem of strong coupling between producers and consumers through a container. Producers and consumers do not communicate with each other directly, and through the blocking queue to communicate, so producers do not have to wait for consumer processing after the production of data, directly to the blocking queue, consumers do not find producers to data, but directly from the blocking queue, the blocking queue is equivalent to a buffer, Balance the processing power of producers and consumers.

  

So, this blocking queue is used to decouple producers and consumers. Throughout most design patterns, a third party is found to decouple, such as the factory model of the third party is the factory class, template mode of the third party is a template class. In the process of learning some design patterns, if we first find the third party of this pattern, we can quickly familiarize ourselves with a design pattern.

the benefits of the producer consumer model
A practical design pattern that is often used to write multithreaded or concurrent code. Here are some of its advantages:
1) Simplify development, you can write the consumer and producer independently or concurrently, it just need to know who the shared object is.
2) Producers do not need to know who is the consumer or how many consumers are the same for consumers
3) Producers and consumers can perform at different speeds
4) Separated consumers and producers can write more concise, readable, maintainable code in a functional capacity

From the hardware design point of view, is actually the hardware design FIFO buffer.

To see a practical application:
In game development, each client connection is equivalent to a separate thread, and each client's operation is asynchronous relative to the other client. For example, to increase the hero's experience, in the logical processing may have a lot of judgment, but anyway, to the end is to update the database, if all the clients are updating the database at the same time, the number of people, the data connection pool is likely to be occupied, so that some updates can not get the connection, there is no way to update data. And the producer and the consumption test pattern solves this problem very well. The logical processing is equivalent to the producer, putting the result data to be updated into the queue, updating the data thread out of the queue and performing the update. And I can also each of the data plus an identifier, the game server all need to update the operation into this queue, this time is equivalent to a number of producers, a consumer thread silently update, can also be updated with multiple consumer threads.

The following is an example of using a blocking queue to implement a producer consumer model:

Import Java.util.concurrent.blockingqueue;import Java.util.concurrent.linkedblockingqueue;import Java.util.logging.level;import Java.util.logging.Logger; Public  class producerconsumerpattern {     Public Static voidMain (String args[]) {//creating Shared ObjectBlockingqueue Sharedqueue =NewLinkedblockingqueue ();//creating Producer and Consumer ThreadThread Prodthread =NewThread (NewProducer (Sharedqueue)); Thread Consthread =NewThread (NewConsumer (Sharedqueue));//starting producer and Consumer threadProdthread.start ();    Consthread.start (); }}//producer Class in Java class Producer implements Runnable {    Private FinalBlockingqueue Sharedqueue; PublicProducer (Blockingqueue sharedqueue) { This. sharedqueue = Sharedqueue; } @Override Public voidRun () { for(intI=0; i<Ten; i++) {Try{System.out.println ("produced:"+ i);            Sharedqueue.put (i); }Catch(Interruptedexception ex) {Logger.getlogger (Producer.class.getName ()). log (Level.severe,NULL, ex); }        }    }}//consumer Class in Java class Consumer implements Runnable{    Private FinalBlockingqueue Sharedqueue; PublicConsumer (Blockingqueue sharedqueue) { This. sharedqueue = Sharedqueue; } @Override Public voidRun () { while(true){Try{System.out.println ("Consumed:"+ Sharedqueue.take ()); }Catch(Interruptedexception ex) {Logger.getlogger (Consumer.class.getName ()). log (Level.severe,NULL, ex); }}}}output:produced:0Produced:1Consumed:0Produced:2Consumed:1Produced:3Consumed:2Produced:4Consumed:3Produced:5Consumed:4Produced:6Consumed:5Produced:7Consumed:6Produced:8Consumed:7Produced:9Consumed:8Consumed:9

Living the consumer model provides a good mode of thinking, flexible use of it, you can get a lot of changes, such as consumer consumption data, may need to continue to deal with, so consumers after processing the data, it also as a producer to put the data in the new queue, to other consumers continue to deal with. Such as:

  

Here, the producer 1 stores the message in the blocking queue 1, the consumer 1 reads the message from the queue, and then hashes the message ID to get one of the n queues, then stores the message in a different queue according to the number, and each blocking queue allocates a thread to consume the data in the blocking queue. If consumer 2 is unable to consume the message, the message is then thrown back into the blocking queue 1 and handed over to other consumers.
In fact, 1 of consumers here can be regarded as a manager and a transit person, responsible for distributing the message to consumers 2, 3, 4.

The following is the code;

 Public  class Msgqueuemanager implements imsgqueue{    Private Static FinalLogger Logger = Loggerfactory.getlogger (Msgqueuemanager.class);//Message Corps column     Public FinalBlockingqueue<message> MessageQueue;PrivateMsgqueuemanager () {messageQueue =NewLinkedtransferqueue<message> (); } Public voidPut (Message msg) {Try{messagequeue.put (msg); }Catch(Interruptedexception e)        {Thread.CurrentThread (). interrupt (); }    } PublicMessage Take () {Try{returnMessagequeue.take (); }Catch(Interruptedexception e)        {Thread.CurrentThread (). interrupt (); }return NULL; }}//Distribute messages, which are responsible for stuffing messages from large queues into small queues    Static  class dispatchmessagetask implements Runnable {@Override Public voidRun () {blockingqueue<message> subqueue; for(;;) {//If there is no data, then block hereMessage msg = Msgqueuefactory.getmessagequeue (). take ();//If empty, it means that no session machine is connected,Need to wait until a session machine is connected while((Subqueue = getinstance (). Getsubqueue ()) = =NULL) {Try{Thread.Sleep ( +); }Catch(Interruptedexception e)                    {Thread.CurrentThread (). interrupt (); }                }//Put the message in a small queue                Try{subqueue.put (msg); }Catch(Interruptedexception e)                {Thread.CurrentThread (). interrupt (); }            }        }    }//Use hash algorithm to get a sub-queue in equilibrium.      PublicBlockingqueue<message> Getsubqueue () {intErrorcount =0; for(;;) {if(Submsgqueues.isempty ()) {return NULL; }int Index= (int) (System.nanotime ()% submsgqueues.size ());Try{returnSubmsgqueues.get (Index); }Catch(Exception e) {//error indicates that the queue has been deleted once after getting the queue sizeLogger.error ("Get Child queue Error", e);if((++errorcount) <3) {Continue; }            }        }    }//When using, we just need to send a message to the corps joins and add a message to the message queue.Imsgqueue messageQueue = Msgqueuefactory.getmessagequeue (); Packet msg = Packet.createpacket (Packet64frametype.type_data,"{}". GetBytes (), ( Short)1); Messagequeue.put (msg);

Reference:
Https://zh.wikipedia.org/wiki/%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85%E9%97%AE%E9%A2%98
Http://www.youxijishu.com/blogs/9.html
Http://www.infoq.com/cn/articles/producers-and-consumers-mode
http://canofy.iteye.com/blog/411408
Https://software.intel.com/zh-cn/blogs/2014/02/28/java
Http://www.uml.org.cn/zjjs/200904161.asp

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Producer Consumer Model (1)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.