Java design patterns (7) - producer - consumer model

  Producer - consumer model is a classic multi-threaded design pattern that provides a good solution for collaboration among multiple threads. In this mode, there are usually two types of thread, that thread a number of producers and consumers of several threads. User producer thread is responsible for submitting the request, the consumer thread is responsible for handling specific tasks producers submitted. Between producers and consumers communicate via shared memory buffer, thus avoiding the producers and consumers to communicate directly, thereby decoupling the producers and consumers. Whether consumption is higher than production or consumption is higher than production, there is a buffer zone to ensure the normal operation of the system. This model has the following roles:

  • Manufacturer: a request for submitting the user, extracts the user tasks, into memory buffer.
  • Consumers: extraction and processing tasks in memory buffer.
  • Memory Buffer: tasks or data cache producers submitted for consumer use.
  • Task: Data Structure producers submitted to the memory buffer.
  • Main: Using Client consumers and producers.

  BlockingQueue which acts as a shared memory buffer for maintenance tasks or data queue (PCData objects). PCData represents a production tasks, or data-related tasks, the producer and consumer objects are objects referenced a BlockingQueue instance. PCData producer is responsible for creating an object, and add it in the queue, consumers get PCData objects from the queue. Below is an example:

  First realize a producer thread that is constructed PCData objects, and placed in a queue BlockingQueue

public class Producer implements Runnable {

    private volatile boolean isRunning = true;
    private BlockingQueue<PCData> queue;                        // 内存缓存区
    private static AtomicInteger count = new AtomicInteger();   // 总数,原子操作
    private static final int SLEEPTIME = 1000;
    
    public Producer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void RUN () { 
        PCDATA Data = null ; 
        the Random R & lt = new new the Random (); 
        System.out.println ( "Start Producer ID =" + Thread.currentThread () getId ().);
         the try {
             the while (isRunning) { 
                the Thread .sleep (SleepTime); 
                data = new new PCDATA (count.incrementAndGet ());     // configuration data tasks 
                System.out.println (data + "IS PUT INTO Queue" );
                 IF (Queue.offer (data, 2, TimeUnit! .SECONDS)) {      // committed to the data cache
                    System.out.println("failed to put data:"+data);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }

    public void stop(){
        isRunning = false;
    }
}

 

  Corresponding to realize a consumer, remove it from the object PCData BlockingQueue queue, and the corresponding calculations.

public class Consumer implements Runnable {

    private BlockingQueue<PCData> queue; 
    private static final int SLEEPTIME = 1000;
    
    public Consumer(BlockingQueue<PCData> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        System.out.println("start Consumer id = "+Thread.currentThread().getId());
        Random r = new Random();
        try {
        while(true){
            PCData data  =this.queue.take();
            if(null!=data){
                int re = data.getData() * data.getData();
                System.out.println(MessageFormat.format("{0}*{1}={2}", data.getData(),data.getData(),re));
                Thread.sleep(r.nextInt(SLEEPTIME));
            }
        }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
}

  PCData object as a shared data between the producer and consumer model, defined as follows:

public class PCData {

    private final int intData;
    public PCData(int d){
        intData = d;
    }
    public PCData(String d){
        intData = Integer.valueOf(d);
    }
    public int getData(){
        return intData;
    }
    @Override
    public String toString() {
        return "intData:" + intData;
    }
    
}

  In the main function, create three producers and three consumers, and allow them to collaborate run, in the main function implementation, as defined in the implementation class LinkedBlockingQueue BlockingQueue queue.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<PCData> queue = new LinkedBlockingQueue<PCData>();
        Producer p1 = new Producer(queue);
        Producer p2 = new Producer(queue);
        Producer p3 = new Producer(queue);
        Consumer c1 = new Consumer(queue);
        Consumer c2 = new Consumer(queue);
        Consumer c3 = new Consumer(queue);
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(p1);
        service.execute(p2);
        service.execute(p3);
        service.execute(c1);
        service.execute(c2);
        service.execute(c3);
        Thread.sleep(10000);
        p1.stop();
        p2.stop();
        p3.stop();
        Thread.sleep(3000);
        service.shutdown();
    }
}

  Producer - consumer model good for producers and consumers thread thread decoupling optimize the overall structure of the system. At the same time, due to the buffering effect, allowing the producer and consumer threads exist performance differences in implementation to address the impact of the performance bottleneck of the system performance to some extent.

Guess you like

Origin www.cnblogs.com/wangyongwen/p/11332436.html