Thread collaboration
Thread communication
- Application scenario: producer and consumer issues
- Suppose that only one product can be stored in the warehouse, the producer puts the produced products into the warehouse, and the consumer takes the products from the warehouse for consumption
- If there is no product in the warehouse, the producer will put the product into the warehouse, otherwise stop production and wait until the product in the warehouse is taken away by the consumer
- If there is a product in the warehouse, the consumer can take the product away for consumption, otherwise stop consumption and wait until the product is put in the warehouse again
This is a thread synchronization problem. Producers and consumers share the same resource, and producers and consumers are interdependent and conditional on each other
- For producers, they should inform consumers to wait before producing products, and after producing products, they need to inform consumers to consume immediately
- For consumers, after consumption, they should inform producers that they have finished consumption and need to produce new products for consumption
- In the producer consumer problem, synchronized is not enough
- synchronized prevents concurrent updates to the same shared resource, enabling synchronization
- synchronized cannot be used for message passing (Communication) between different threads
Java provides several methods to solve the communication problem between threads
Method name | effect |
---|---|
wait() | It means that the thread waits until other threads notify it. Unlike sleep, it will release the lock and can only be in the synchronization block |
wait(long timeout) | Specifies the number of milliseconds to wait |
notify() | Wake up a waiting thread |
notifyAll() | Wake up all threads calling the wait() method on the same object, and the threads with high priority are scheduled first |
Note: all methods of Object class can only be used in synchronization methods or synchronization code blocks, otherwise an exception IIIegalMonitorStateException will be thrown
Solution 1:
Concurrent collaboration model "producer / consumer model" - > management process method
-
Producer: module responsible for production data (may be method, object, thread, process);
-
Consumer: module responsible for processing data (may be method, object, thread, process);
-
Buffer: consumers cannot directly use the producer's data. There is a buffer between them
The producer puts the produced data into the buffer, and the consumer takes out the data from the buffer
Producer -- data buffer -- Consumer
Solution 2:
Concurrent collaboration model "producer / consumer model" -- > semaphore method
Pipe program method
package com.Sucker.gaoji; //Test: producer consumer model -- > using buffer solution //Producer consumer product buffer public class TestPC { public static void main(String[] args) { SynContainer container = new SynContainer(); new Productor(container).start(); new Consumer(container).start(); } } //producer class Productor extends Thread{ SynContainer container; public Productor(SynContainer container){ this.container = container; } //production @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Produced"+i+"Chicken"); container.push(new Chicken(i)); } } } //consumer class Consumer extends Thread{ SynContainer container; public Consumer(SynContainer container){ this.container = container; } //consumption @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Consumption"+container.pop().id+"Chicken"); } } } //product class Chicken{ int id;//Product number public Chicken(int id) { this.id = id; } } //buffer class SynContainer{ //A container size is required Chicken[] chickens = new Chicken[10]; //Container counter int count = 0; //The producer puts in the product public synchronized void push(Chicken chicken){ //If the container is full, it needs to wait for consumers to consume if(count == chickens.length){ //Inform consumers of consumption, production and waiting try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //If it is not full, it needs to throw in the product chickens[count] = chicken; count++; //If you have a product, you can inform consumers to consume it this.notifyAll(); } //Consumer products public synchronized Chicken pop(){ //Judge whether it can be consumed if(count==0){ //Wait for producers to produce, consumers to wait try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //If you can consume count--; Chicken chicken = chickens[count]; //When finished, inform the producer to produce this.notifyAll(); return chicken; } }
Signal lamp method
package com.Sucker.gaoji; //Test producer consumer problem 2: signal lamp method, flag bit solution public class TestPC2 { public static void main(String[] args) { TV tv = new TV(); new Player(tv).start(); new Watcher(tv).start(); } } //Producer -- > actor class Player extends Thread{ TV tv; public Player(TV tv){ this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if(i%2==0) this.tv.play("Happy base camp"); else this.tv.play("Tiktok"); } } } //Consumer -- > audience class Watcher extends Thread{ TV tv; public Watcher(TV tv){ this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { tv.watch(); } } } //Products -- > Programs class TV{ //The actor performs and the audience waits for T //The audience watched and the actors waited for F String voice; boolean flag = true; //perform public synchronized void play(String voice){ if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("The actors performed"+voice); //Inform the audience to watch this.notifyAll();//Notification wake up this.voice = voice; this.flag = !this.flag; } //watch public synchronized void watch(){ if(flag){//The audience waited to watch try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Watched"+voice); //Inform the actors to perform this.notifyAll(); this.flag = !this.flag; } }