Communication between threads

When using threads to run multiple tasks, you can use locks to synchronize the behavior of two tasks, so that one task will not interfere with another task. This is to solve the problem of interference between threads. Now we need to solve the problem of coordination between threads, that is, the problem of communication between threads From Baidu

In fact, I haven't been very clear about the concept of thread during my work. As long as it doesn't run independently, it will involve the interaction between threads, so it belongs to the communication between threads

  • join: one thread lets another thread execute and complete
  • Producer / Consumer: it is the coordination between producers and consumers

I. wait and notify/notifyAll

Before delving into this section, I want to raise the question: what is thread communication
When multiple threads are processing the same resource and different tasks, thread communication is needed to help solve the use or operation of the same variable between threads. In other words, when multiple threads operate on the same data, they avoid operating on the same variable, resulting in contention for variable resources.
When facing this problem, we will think that if one thread can fall asleep and wait for a rest to operate the task, it will not compete, and there will be a sense of order.
In this case, we introduce the wake-up mechanism: (wait(),notify())
After a thread performs the specified operation, I will enter the wait state, and then wake up the thread after other threads complete the specified task.

wait() method

Before other threads call the notify method or notifyAll method of the object, my current thread will wait.
When a thread calls the wait() method, it will release its ownership of the lock and wait for another thread to notify it. Of course, the way to wake up the thread cannot be_‘ Hey! You should get up and go to work! "_ He has a fixed method. For example, the notify and notifyAll methods can be used to obtain the ownership of the lock.
~ attention
To ensure that you have a lock when calling the wait() method, you have to ensure that the call of the wait() method must be placed in the synchronized method or synchronized block.

notify() method

The notify() method wakes up a thread waiting for the current object lock

notifyAll() method

The notifyAll() method wakes up all threads waiting on this object monitor

~ attention
If multiple threads are waiting, one of them will choose to wake up.
This choice is arbitrary and related to concrete implementation.
The notify() method should be called by the thread that owns the lock of the object.
The notifyAll() method is the same

Two thread instance

In fact, it is not difficult to understand that the best example between threads is the producer consumer model, so let's imitate an example of producer consumer;

Method of producing milk and method of consumption

package ThreadDemo;

/**
 * Created by jdx on 2021/12/29 3:56 PM
 */
public class Milk {
    //Milk cow number
    private int cowsId;
    //milk
    private int bottles;

    //Method for producing milk
    public synchronized void MilkTheCow() {
        //When the number of milk bottles produced by milk is not 0, the method of producing milk stops
        if (bottles != 0) {
            try {
                //Wait thread
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //Then when my number of milk bottles is 0, the cow begins to produce milk
        bottles = bottles + 1;
        //In order to distinguish which cow produces which bottle of milk, the cow number must also be distinguished
        cowsId = cowsId + 1;
        //Access to milk producing cows
        String cowName = Thread.currentThread().getName();
        //Output from console
        System.out.println(cowName + " A bottle numbered" + cowsId + " milk");
        //From this point on, you have to wake up other waiting threads
        notify();
    }

    //Method of consuming milk
    public synchronized void drinkMilk() {
        //When the number of milk bottles is 0, this method is in the waiting state
        if (bottles == 0) {
            try {
                wait();
                //InterruptedException is an 'interrupt exception' thrown by methods such as wait sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //Consumption of milk
        bottles = bottles - 1;
        //People as consumers
        String people = Thread.currentThread().getName();
        //Output from console
        System.out.println(people + "Drank a milk, number:" + cowsId);
        //Wake up other threads after execution
        notify();
    }
    //get set method


    public int getCowsId() {
        return cowsId;
    }

    public void setCowsId(int cowsId) {
        this.cowsId = cowsId;
    }

    public int getBottles() {
        return bottles;
    }

    public void setBottles(int bottles) {
        this.bottles = bottles;
    }
    //Nonparametric structure

    public Milk() {
        super();
    }

    //Parametric structure

    public Milk(int cowsId, int bottles) {
        super();
        this.cowsId = cowsId;
        this.bottles = bottles;
    }
}

Class for producing milk

package ThreadDemo;

/**
 * Created by jdx on 2021/12/30 6:01 PM
 */
public class cows extends Thread {
    //Class for obtaining milk
    private Milk milk;

    //Nonparametric structure
    public cows() {
        super();
    }

    //Parametric structure
    public cows(Milk milk) {
        super();
        this.milk = milk;
    }

    //get set method
    public Milk getMilk() {
        return milk;
    }

    public void setMilk(Milk milk) {
        this.milk = milk;
    }
    //Override run method

    @Override
    public void run() {
        productMilk();
    }

    private void productMilk() {
        //25 bottles of milk are produced by default
        for (int i = 0; i < 2; i++) {
            //Call the method of producing milk
            milk.MilkTheCow();
        }
    }
}

Class consuming milk

package ThreadDemo;

/**
 * Created by jdx on 2021/12/30 6:12 PM
 */
public class people extends Thread {
    //Class for obtaining milk
    private Milk milk;

    //get set method

    public Milk getMilk() {
        return milk;
    }

    public void setMilk(Milk milk) {
        this.milk = milk;
    }
    //Override run method

    @Override
    public void run() {
        drink();
    }

    private void drink() {
        for (int i = 0; i < 2; i++) {
            //Call the method of consuming milk
            milk.drinkMilk();
        }
    }


    //Parametric structure
    public people(Milk milk) {
        super();
        this.milk = milk;
    }

    //Nonparametric structure
    public people() {
        super();
    }

}

Test unit

package basics;

import ThreadDemo.Milk;
import ThreadDemo.cows;
import ThreadDemo.people;

/**
 * Created by jdx on 2021/12/30 6:17 PM
 */
public class milkTest {
    public static void main(String[] args) {
        //new a Milk class
        Milk milk = new Milk();
        //new is a cow class
        cows cow = new cows(milk);
        //new is a people class
        people humanity = new people(milk);
        //new a thread containing producers
        Thread threadCow = new Thread(cow, "Producer: cow");
        //new a thread containing consumers
        Thread threadHum = new Thread(cow, "Consumer: Human");
        //Start thread
        threadCow.start();
        threadHum.start();
    }
}

More insights

Keywords: Java Back-end

Added by Mount Tropolis on Fri, 31 Dec 2021 15:58:43 +0200