1. Concept
The problem of producers and consumers is a problem of multi-threaded collaboration in Jindian. The producers are responsible for producing products and storing them in the warehouse; consumers obtain products from the warehouse and consume them. When the warehouse is full, the producer must stop production until there is a location for the product to be stored; when the warehouse is empty, the consumer must stop consumption until there is a product in the warehouse.
The following techniques are mainly used to solve producer/consumer problems: 1. Use threads to simulate producers and continuously store products in the warehouse in the run method. 2. Use threads to simulate consumers and continuously obtain products from the warehouse in the run method. 3
The . Warehouse class saves the product. When the number of products is 0, the wait method is called, causing the current consumer thread to enter a waiting state. When a new product is stored, the notify method is called to wake up the waiting consumer thread. When the warehouse is full, the wait method is called, causing the current producer thread to enter a waiting state. When a consumer obtains the product, the notify method is called to wake up the waiting producer thread.
2. Examples
package book.thread.product;public class Consumer extends Thread{ private Warehouse warehouse;//The warehouse where the consumer obtains the product private boolean running = false;//Is the flag bit of the end thread required public Consumer(Warehouse warehouse,String name){ super(name); this.warehouse = warehouse; } public void start(){ this.running = true; super.start(); } public void run(){ Product product; try { while(running){ //Get product from the warehouse product = warehouse.getProduct(); sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } //Stop the consumer thread public void stopConsumer(){ synchronized(warehouse){ this.running = false; warehouse.notifyAll();//Notify thread waiting for the warehouse} } //Whether the consumer thread is running public boolean isRunning(){ return running; }} package book.thread.product;public class Producer extends Thread{ private Warehouse warehouse;//The manufacturer stores the product's warehouse private static int produceName = 0;//The product's name private boolean running = false;//The flag bit of the end thread is required public Producer(Warehouse warehouse,String name){ super(name); this.warehouse = warehouse; } public void start(){ this.running = true; super.start(); } public void run(){ Product product; //Produce and store the product try { while(running){ product = new Product((++productName)+""); this.warehouse.storageProduct(product); sleep(300); } } catch (InterruptedException e) { e.printStackTrace(); } } //Stop the producer thread public void stopProducer(){ synchronized(warehouse){ this.running = false; //Notify the thread waiting for the warehouse warehouse warehouse warehouse.notifyAll(); } } //Whether the producer thread is running public boolean isRunning(){ return running; }} package book.thread.product;public class Product { private String name;//Product name public Product(String name){ this.name = name; } public String toString(){ return "Product-"+name; }} package book.thread.product;//The warehouse class of the product uses an array to represent a circular queue to store the product public class Warehouse { private static int CAPACITY = 11;//The capacity of the warehouse private Product[] products;//Products in the warehouse//Products in the [front,rear] interval are not consumed private int front = 0;//Subscript of the first unconsumed product in the current warehouse private int rear = 0;//Subscript of the last unconsumed product in the warehouse plus 1 public Warehouse(){ this.products = new Product[CAPACITY]; } public Warehouse(int capacity){ this(); if(capacity > 0){ CAPACITY = capacity +1; this.products = new Product[CAPACITY]; } } //Get a product from the warehouse public Product getProduct() throws InterruptedException{ synchronized(this){ boolean consumerRunning = true;//Tag whether the consumer thread is still running Thread currentThread = Thread.currentThread();//Get the current thread if(currentThread instance of Consumer){ consumerRunning = ((Consumer)currentThread).isRunning(); }else{ return null;//Not consumer can obtain the product} //If the consumer thread is running, but there is no product in the warehouse, the consumer thread continues to wait while((front==rear) && consumerRunning){ wait(); consumerRunning = ((Consumer)currentThread).isRunning(); } //If the consumer thread has stopped running, exit the method and cancel the product if(!consumerRunning){ return null; } //Get the first product that has not been consumed at present Product product = products[front]; System.out.println("Consumer[" + currentThread.getName()+"] getProduct:"+product); //Move the subscript of the currently unconsumed product back one by one, if it reaches the end of the array, move to the header front = (front+1+CAPACITY)%CAPACITY; System.out.println("The quantity of products not yet consumed in the warehouse: "+(rear+CAPACITY-front)%CAPACITY); //Notify other waiting threads notify(); return product; } } //Storage a product to the warehouse public void storageProduct(Product product) throws InterruptedException{ synchronized(this){ boolean producerRunning = true;//Signify whether the producer thread is running Thread currentThread = Thread.currentThread(); if(currentThread instance of Producer){ producerRunning = ((Producer)currentThread).isRunning(); }else{ return; } //If the last unconsumed product is next to the subscript of the first unconsumed product, it means there is no storage space. //If there is no storage space and the producer thread is still running, the producer thread waits for the warehouse to release the product while(((rear+1)%CAPACITY == front) && producerRunning){ wait(); producerRunning = ((Producer)currentThread).isRunning(); } //If the production thread has stopped running, the product's storage is stopped if(!producerRunning){ return; } //Save the product to the warehouse products[rear] = product; System.out.println("Producer[" + Thread.currentThread().getName()+"] storageProduct:" + product); //Change the rear subscript by one after another. Rear = (rear + 1)%CAPACITY; System.out.println("The quantity of products not consumed in the warehouse: "+(rear + CAPACITY -front)%CAPACITY); notify(); } }} package book.thread.product;public class TestProduct { public static void main(String[] args) { Warehouse warehouse = new Warehouse(10);//Create a warehouse with a capacity of 10 //Create producer threads and consumer Producer producers1 = new Producer(warehouse,"producer-1"); Producer producers2 = new Producer(warehouse,"producer-2"); Producer producers3 = new Producer(warehouse,"producer-3"); Consumer consumer1 = new Consumer(warehouse,"consumer-1"); Consumer consumer2 = new Consumer(warehouse,"consumer-2"); Consumer consumer3 = new Consumer(warehouse,"consumer-3"); Consumer consumer4 = new Consumer(warehouse,"consumer-4"); //Start the producer thread and the consumer thread produces1.start(); producers2.start(); consumer1.start(); producers3.start(); consumer2.start(); consumer3.start(); consumer4.start(); //Let the producer/consumer program run for 1600ms try { Thread.sleep(1600); } catch (InterruptedException e) { e.printStackTrace(); } //Stop the consumer thread produces1.stopProducer(); consumer1.stopConsumer(); producers2.stopProducer(); consumer2.stopConsumer(); producers3.stopProducer(); consumer3.stopConsumer(); consumer4.stopConsumer(); }}Output result:
Producter[producter-1] storageProduct: The number of products that have not been consumed in the Product-1 warehouse: 1Consumer[consumer-2] getProduct: The number of products that have not been consumed in the Product-1 warehouse: 0Producer[producter-3] storageProduct: The number of products that have not been consumed in the Product-3 warehouse: 1Producer[producter-2] storageProduct: The number of products that have not been consumed in the Product-2 warehouse: 2Consumer[consumer-3] getProduct: The number of products that have not been consumed in the Product-3 warehouse: 1Consumer[consumer-1] getProduct: The number of products that have not been consumed in the Product-2 warehouse: 0Producer[producter-1] storageProduct: The number of products that have not been consumed in the Product-4 warehouse: 1Consumer[consumer-4] getProduct: The number of products that have not been consumed in the Product-4 warehouse: 0Producer[producter-3] storageProduct: The number of products that have not been consumed in the Product-6 warehouse: 1Producer[producter-2] storageProduct: The number of products that have not been consumed in the Product-5 warehouse: 2Consumer[consumer-1] getProduct: The number of products that have not been consumed in the Product-6 warehouse: 1Consumer[consumer-2] getProduct: The number of products that have not been consumed in the Product-5 warehouse: 0Producer[productr-1] storageProduct: The number of products that have not been consumed in the Product-7 warehouse: 1Consumer[consumer-3] getProduct: The number of products that have not been consumed in the Product-7 warehouse: 0Producer[productr-3] storageProduct: The number of products that have not been consumed in the Product-8 warehouse: 1Producer[producer-2] storageProduct:Product-9 Number of products that have not been consumed in the warehouse: 2Consumer[consumer-4] getProduct:Product-8 Number of products that have not been consumed in the warehouse: 1Producer[productr-1] storageProduct:Product-10 Number of products that have not been consumed in the warehouse: 2Producer[productr-3] storageProduct:Product-11 Number of products that have not been consumed in the warehouse: 3Producer[productr-2] storageProduct:Product-12 Number of products that have not been consumed in the warehouse: 4Consumer[consumer-1] getProduct:Product-9 Number of products that have not been consumed in the warehouse: 3Consumer[consumer-2] getProduct:Product-10 Number of products that have not been consumed in the warehouse: 2Consumer[consumer-3] getProduct:Product-11 Number of products that have not been consumed in the warehouse: 1Producer[productr-3] storageProduct:Product-13 Number of products that have not been consumed in the warehouse: 2Producer[productr-1] storageProduct:Product-14 Number of products that have not been consumed in the warehouse: 3Producer[producer-2] storageProduct:Product-15 Number of products that have not been consumed in the warehouse: 4Consumer[consumer-4] getProduct:Product-12 Number of products that have not been consumed in the warehouse: 3Consumer[consumer-1] getProduct:Product-13 Number of products that have not been consumed in the warehouse: 2Consumer[consumer-2] getProduct:Product-14 Number of products that have not been consumed in the warehouse: 1Producer[productr-1] storageProduct:Product-16 Number of products that have not been consumed in the warehouse: 2Producer[producer-3] storageProduct: Number of products that have not been consumed in the Product-17 warehouse: 3Producer[productr-2] storageProduct: Number of products that have not been consumed in the Product-18 warehouse: 4
Analysis: A product warehouse is established in the main method, and the warehouse does not associate 3 producer threads and 4 consumer threads. These threads are started to make the producer/consumer model work. When the program runs for 1600ms, all producers stop producing products and consumers stop consuming products.
The producer thread Product produces a product without 300ms in the run method and stores it in the warehouse; the consumer thread Consumer takes a product from the warehouse without 500ms in the run method.
Warehouse is responsible for storing and distributing products. The storageProduct method is responsible for storing the product. When the warehouse is full, the current thread enters a waiting state, that is, if producer thread A calls the storageProduct method to store the product, it finds that the warehouse is full and cannot be stored, it will enter a waiting state. When the storage product is successful, the notify method is called to wake up the waiting consumer thread.
The getProduct method is responsible for the product in advance. When the warehouse is empty, the current thread enters a waiting state. That is, if consumer thread B calls the getProduct method to obtain the product, it finds that the warehouse is empty, it will enter a waiting state. When the product is extracted successfully, the notify method is called to wake up the waiting producer thread.
The above article briefly discusses the problems of producers and consumers in Java threads is all the content I share with you. I hope it can give you a reference and I hope you can support Wulin.com more.