JavaSE advanced multithreading -- thread collaboration

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 nameeffect
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;
    }

}

Keywords: Java Back-end Multithreading JavaSE

Added by doni49 on Fri, 24 Dec 2021 04:00:15 +0200