Problem: a classic case of multithreading is the problem of producers and consumers To operate the same resource together is to produce one product and consume another, which must take into account the safe synchronization of threads How to realize thread safety in multithreading and ensure the unity of resources
In the producer and consumer problem, both producers and consumers are multithreaded operations
Here is an object that executes the actions of producers and consumers. It is necessary to judge the products, and judge when to produce and when to consume
/**Operation data*/ class Product{ int num;//Number of products //Let the producer produce and start production when the quantity is less than 20 public synchronized void addProduct(){ if (num>=20){//If it is greater than 20, there is no need to produce try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }else { num++; System.out.println("The producer begins to produce the second product"+ num +"Piece product"); notifyAll();//If the number of products is greater than 0, the consumption thread that stops when the number is less than 0 can be awakened } } //Let consumers consume, as long as the quantity is greater than 0, they can start to consume //Consumption action public synchronized void reduceProduct(){ if (num>0){ System.out.println("Consumers start spending"+ num +"Piece product"); num--; notifyAll();//If the quantity is greater than 0, consumption can start. When the product data is 20, reduce the products, and then the producers can also start production. Therefore, wake up the producers }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Producer's execution code:
/**producer*/ class Producer implements Runnable{ Product product;//Introduce the object to operate on public Producer(Product product) { this.product = product; } @Override public void run() { while (true){ this.product.addProduct(); } } }
Consumer's execution code:
/**consumer*/ class Consumer implements Runnable{ Product product; public Consumer(Product product) { this.product = product; } @Override public void run() { while (true){ this.product.reduceProduct(); } } }
The above is based on the idea of Shang * * of an organization. The following is the crazy God's management method in station B (solved through buffer zone)
Shared products
/**product*/ class Clicken{ int id;//number public Clicken(int id) { this.id = id; } }
Producer's execution code
/**producer*/ class Productor extends Thread{ SynContainer synContainer; public Productor(SynContainer synContainer){ this.synContainer =synContainer; } @Override public void run() {//Production action for (int i = 1; i < 100; i++) { synContainer.push(new Clicken(i)); System.out.println("Produced" + i +"Chicken"); } } }
Consumer's execution code
/**consumer*/ class Customer extends Thread{ SynContainer synContainer; public Customer(SynContainer synContainer){ this.synContainer =synContainer; } @Override public void run() { //Consumption action for (int i = 0; i < 100; i++) { System.out.println("Consumption" + synContainer.pop().id +"Chicken"); } } }
buffer
/**buffer*/ class SynContainer{ Clicken[] clickens = new Clicken[10]; //The need for a container size means that within this range, producers and consumers decide whether to carry out production or consumption int count = 0;// //Container counter number of chickens /**Producers put in products*/ public synchronized void push(Clicken clicken){ if (count == clickens.length){ //If the container is full, wait for the consumer to consume. / / inform the consumer to consume and wait for production try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } clickens[count] = clicken;//If the container is not full, it needs to be produced by the producer count++; //Inform consumers that they can consume this.notify(); } /**Consumer products*/ public synchronized Clicken pop(){ if (count==0){ //Judge whether it can be consumed or not -- > it needs to be produced by the producer try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } count--;//Can consume -- > consumer consumption Clicken clicken = clickens[count]; //Inform the producer of production this.notify(); return clicken; } }
The execution entry of both is
public static void main(String[] args) { Product product = new Product(); Producer producer = new Producer(product); Consumer consumer = new Consumer(product); new Thread(producer).start(); new Thread(consumer).start(); }
The above two ideas are roughly the same. When writing these codes, I was a little confused about why I had to judge whether to carry out production and consumption actions in an independent object. I was still a little confused when watching the videos of Shang Silicon Valley, and then compared the crazy idea. In fact, this is an idea of object-oriented programming, The data shared by the two are independent, and then the producer is only responsible for generation and the consumer is only responsible for consumption. They perform their respective duties. The operations that need to be judged are placed in another object to reduce the coupling of the code In fact, my personal understanding of object-oriented programming is not enough. The road is long and blocked