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