Article directory
Waiting awakening mechanism
Inter-thread communication
Concept: Multiple threads are processing the same resource, but the actions (tasks of threads) are different.
For instance:
I like instant noodles, my roommate Junieson I like instant noodles for me to eat. If I understand instant noodles as resources for me and my roommate to accomplish one thing together (that is, I eat his instant noodles, hip-hopping), thread A production (my roommate's instant noodles), thread B consumption (I want instant noodles), then there is communication problem between thread A and thread B.
When multiple threads are executed concurrently, by default, the CPU switches threads randomly. If we need multiple threads to accomplish a task together, and we want them to execute regularly, then some coordinated communication between threads is needed to help us achieve multi-threads to operate a data together. That's why we need to be able to handle inter-thread communication.
When multiple threads are dealing with the same resource and tasks are different, threads need to communicate to help resolve the use or operation of the same variable between threads. When multiple threads operate on the same data, they avoid competing for the same shared variable. That is to say, we need to make effective use of resources by various threads through certain means. And that means waiting for the wake-up mechanism. Here is the main point of this article.
Overview of Waiting for Wake-up Mechanism
Waiting for wake-up mechanism:
This is a collaboration mechanism between multiple threads. When it comes to threads, we often think about race s between threads, such as scrambling for locks, but that's not the whole story. There's also a collaboration mechanism between threads.
After a thread has performed a specified operation, it enters a waiting state (wait ()) and waits for other threads to execute their specified code before waking up (notify (). When there are multiple threads waiting, if necessary, notify all () can be used to wake up all waiting threads.
Again, wait/notify is a collaborative mechanism between threads.
When the thread is over, I'll go to it. Deep Understanding of Object Classes This article completes, has the friend who has read recalled? These three methods, each class inherited from the Object class!
Here's a little introduction: Waiting for the wake-up mechanism:
Waiting for wake-up mechanism is used to solve the problem of inter-thread communication. The meaning of the three methods used is as follows:
- Wait: Threads are no longer active, no longer participate in scheduling, enter the wait set, so they will not waste CPU resources, nor compete for locks. At this time, the thread state is WAITING. It also waits for other threads to perform a special action, that is, notify, where the thread waiting on the object is released from the wait set and re-entered into the ready queue.
- Notfy: Select a thread in the wait set of the notified object to release.
- NotfyAll: Releases all threads on the wait set of the notified object.
Note: Even if only one waiting thread is notified, the notified thread cannot immediately resume execution, because it interrupts in the synchronization block, and now it does not hold a lock, so it needs to try again to acquire the lock (probably facing competition from other threads) before it can resume execution after the original call of the wait method.
In other words:
- If the lock can be acquired, the thread will change from WAITING state to RUNNABLE state.
- Otherwise, from wait set to entry set, the thread changes from WAITING state to BLOCKED state.
Details to note when calling wait and notify methods:
- The wait method and the notify method must be invoked by the same lock object. Because: the corresponding lock object can wake up the thread using the wait method called by the same lock object through notify.
- The wait method and notify method belong to the Object class. Because: the lock object can be any object, and the class of any object is inherited from the Object class.
- The wait method and the notify method must be used in the synchronization block or the synchronization function. Because: these two methods must be invoked through the lock object.
Specific details:
void notify()
Wakes up a single thread that is waiting on this object's monitor.
void notifyAll()
Wakes up all threads that are waiting on this object's monitor.
void wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
Waiting for Wake-up Mechanism Code Demonstration
A requirement analysis is required for the following demonstration
Resource class: Bubble noodle class
Setting the properties of bubbles
Noodles
soup
Status: true, no false
Producer (my roommate) class: is a thread class that can inherit Thread
Setting Thread Task (run): Bubble Surface
Judging the state of bubble surface
true: Bubble noodles
My roommate calls wait to wait
false: No instant noodles
My roommate's bubble noodles
Consider my appetite: My roommate alternately pickles two flavors of instant noodles (braised beef noodles, pickled beef noodles)
Two states (i% 2 = 0)
By soaking Noodles
Modify the state of bubble surface to true
Wake up the consumer thread (call me up to sleep in bed), tell me to eat instant noodles, (Meizizi, if only a few more eggs)
The consumer (I) is a threaded class that inherits Thread
Setting Thread Task (run): Eating Bubble Noodles
Judgment of bubble surface state
false: No instant noodles
I call the wait method to enter the wait state
true: Soaked noodles
I eat instant noodles.
I finished eating instant noodles.
Modify the bubble surface status to false no more
I wake up my roommate's bubble noodles
Test code:
public class Main { public static void main(String args[]) { //Creating Bubble Face Objects PaoMian pm = new PaoMian(); //Create Roommate Threads, Open, Bubble Noodles new RoomMate(pm).start(); //Create my thread, open, eat instant noodles new Me(pm).start(); } } class PaoMian{ //Noodles private String noddle; //soup private String soup; //state private boolean flag = false; public String getNoddle() { return noddle; } public String getSoup() { return soup; } public boolean isFlag() { return flag; } public void setNoddle(String noddle) { this.noddle = noddle; } public void setSoup(String soup) { this.soup = soup; } public void setFlag(boolean flag) { this.flag = flag; } } //Be careful: //By Thread and Bubble Thread Relations - > Communication (Mutual Exclusion) //Synchronization technology must be used to ensure that only one thread can execute //The lock object must be unique. Obviously, to select foam surface, we need foam surface variables. class RoomMate extends Thread{ //Bun variables private PaoMian pm; public RoomMate(PaoMian pm){ this.pm = pm; } @Override public void run() { int count=0; while (true){ //Bubble noodles all the time synchronized (pm){ if(pm.isFlag() == true){ try { pm.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Execute after waking up, bubble noodles //Alternately soak two flavors of instant noodles if(count % 2 == 0){ pm.setNoddle("Braised beef noodle"); pm.setSoup("Spicy broth"); }else { pm.setSoup("Sauerkraut soup"); pm.setNoddle("Pickled cabbage noodles"); } count++; System.out.println("Dear Roommate,Bubble noodles are in production:"+pm.getSoup()+","+pm.getNoddle()); //It takes five minutes to make noodles. Here's 2 seconds. try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //After the end of production, the state becomes as follows pm.setFlag(true); //Wake up my thread to eat instant noodles pm.notify(); System.out.println("Dear Roommate,Soak up the noodles:"+pm.getSoup()+","+pm.getNoddle()); } } } } class Me extends Thread{ private PaoMian pm; public Me(PaoMian pm){ this.pm = pm; } @Override public void run() { while (true){ synchronized (pm){ if(pm.isFlag() == false){ try { pm.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //After the thread is awakened System.out.println("I am eating.:"+pm.getNoddle()+","+pm.getSoup()); //Finished buns pm.setFlag(false); //Wake up roommate bubble noodles pm.notify(); System.out.println("I ate and played.:"+pm.getNoddle()+","+pm.getSoup()+",Roommates prepare bubble noodles"); System.out.println("**********************************"); } } } }
Result:
Ha Ha Mei Zi
To tell you the truth, my roommate never made instant noodles for me. Haha, welcome to his blog! Shh, there are babies in it.
Portal
Status of threads
Overview of the status of threads
If you have any conditions, you can see Mr. Liu Xin's <Manon Turns over> in which the thread of story telling is very vivid. I remember that he gave us a lecture last year when he returned to his alma mater, which was inspired deeply and was one of the important enlightening teachers in our university.
When a thread is created and started, it neither enters the execution state as soon as it is started, nor is it always in the execution state. In the lifecycle of a thread,
Six thread states are given in the enumeration java.lang.Thread.State in the API:
The conditions for each thread state to occur are listed here, and each state will be parsed in detail below.
Posting helps understand:
Attention should be paid to conversion relationship and usufruct of CPU
Timed waiting
Timed Waiting Thread Status Diagram:
Note: The time specified in sleep() is the shortest time a thread will not run. Therefore, the sleep() method does not guarantee that the thread will start executing immediately after sleep expires.
BLOCKED
The Blocked state is introduced in the API as a state in which a thread is blocking waiting for a monitor lock (lock object).
For example, thread A uses the same lock as thread B code. If thread A acquires the lock and thread A enters the Runnable state, then thread B enters the Blocked lock blocking state.
This is from the Runnable state to the Blocked state.
In addition, the Waiting and Time Waiting States will also be blocked in some cases.
Blocked Thread Status Diagram
Waiting (unlimited waiting)
Wating state is described in the API as: a thread that is waiting indefinitely for another thread to perform a special (wake-up) action is in this state.
It's like a roommate's instant noodles, I wait to eat, when it's ready, when it's time to eat (aside from this topic, I'm not going to soak, because I'm lazy ~)
It can be seen that waiting state is not the operation of a thread. It embodies the communication between threads. It can be understood as the cooperative relationship between threads. Many threads will strive for locks, and there is a cooperative relationship between them.
When multiple threads cooperate, such as A and B threads, if A threads call wait() method in Runnable state, then A threads enter Waiting state and lose synchronization lock. If the B thread gets the synchronization lock and calls the notify() method in the running state, it will wake up the infinite waiting thread A. Note that if a lock object is acquired, thread A will wake up and enter Runnable state; if no lock object is acquired, it will enter Blocked state.
Waiting Thread State Diagram
/* Waiting for wake-up cases: communication between threads Create a customer thread (consumer):Tell your boss the type and quantity of steamed buns you want,Call the wait method, abandon the execution of the cpu, and enter the WAITING state (unlimited waiting) Create a Boss Thread (Producer): Take 5 seconds to make steamed buns. After making the steamed buns, call notify method to wake up customers to eat steamed buns. Be careful: Customer and boss threads must be wrapped in synchronous code blocks to ensure that there is only one execution waiting and waking up. The lock object used synchronously must be guaranteed uniqueness Only lock objects can call wait and notify methods Obejct Methods in classes void wait() Causes the current thread to wait before other threads call the notify() method or notifyAll() method of this object. void notify() Wake up a single thread waiting on this object monitor. The code after the wait method continues to execute */ public class Main{ public static void main(String[] args) { //Create lock objects to ensure uniqueness Object obj = new Object(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //Waiting to buy steamed buns while(true){ //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("Tell your boss the type and quantity of steamed buns you want"); //Call the wait method, abandon the execution of the cpu, and enter the WAITING state (unlimited waiting) try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed buns are ready.,Open to eat!"); System.out.println("---------------------------------------"); } } } }.start(); //Create a Boss Thread (Producer) new Thread(){ @Override public void run() { //Make steamed buns all the time while (true){ //It took five seconds to make steamed buns. try { Thread.sleep(5000);//Take 5 seconds to make steamed buns } catch (InterruptedException e) { e.printStackTrace(); } //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("The boss makes the steamed buns in five seconds,Inform customers,You can eat steamed buns."); //After making the steamed bun, call notify method to wake up the customer to eat the steamed bun. obj.notify(); } } } }.start(); } }
supplement
Comprehensive nature:
When you look through the API, you will find that Timed Waiting is still closely related to Waiting status.
For example, the wait method in the Waiting (infinite waiting) state is empty, while the wait method in the timed waiting (timed waiting) state is parameterized.
This method with parameters is actually a countdown operation, which is equivalent to the small alarm clock in our life. We set the time and notify the time in time. But if we get the notice in advance, then setting the time would be a waste of effort, so this design scheme is actually killing two birds with one stone. If no notification is received, the thread is in the Timed Waiting state until the countdown is completed and automatically wakes up; if it is notified during the countdown, the thread wakes up immediately from the Timed Waiting state.
In order to better understand the Object class, here we introduce wait's parametric method and notifAll method.
void wait(long timeout)
Causes the current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
void notifyAll()
Wakes up all threads that are waiting on this object's monitor.
Demonstration wait(long timeout)
Note that only customers: thread wakes up automatically
//There are two ways to get into Timewaiting // 1. Using the sLeep (Long m) method, the thread wakes up to the Runnable/Blocked state after the end of the millisecond value. // 2. Using the wait (Long m) method, if the wait method has not been notify wake up after the end of the millisecond value, it will automatically wake up, and the thread wakes up into the Runnable/BLocked state. public class Main{ public static void main(String[] args) { //Create lock objects to ensure uniqueness Object obj = new Object(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //Waiting to buy steamed buns while(true){ //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("Tell your boss what kind and quantity of buns you want"); //Call the wait method, abandon the execution of the cpu, and enter the WAITING state (unlimited waiting) try { obj.wait(3000); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed buns are ready.,Open to eat!"); System.out.println("---------------------------------------"); } } } }.start(); } }
Result:
Use wake-up operation
Test notifyAll() to wake up all threads waiting on this object monitor.
Multiple customers
//There are two ways to get into Timewaiting // 1. Using the sLeep (Long m) method, the thread wakes up to the Runnable/Blocked state after the end of the millisecond value. // 2. Using the wait (Long m) method, if the wait method has not been notify wake up after the end of the millisecond value, it will automatically wake up, and the thread wakes up into the Runnable/BLocked state. public class Main{ public static void main(String[] args) { //Create lock objects to ensure uniqueness Object obj = new Object(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //Waiting to buy steamed buns while(true){ //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("Customer 1 informs the owner of the type and quantity of steamed buns he wants"); //Call the wait method, abandon the execution of the cpu, and enter the WAITING state (unlimited waiting) try { obj.wait(3000); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed buns are ready.,Customer 1 eats!"); System.out.println("---------------------------------------"); } } } }.start(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //Waiting to buy steamed buns while(true){ //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("Customer 2 informs the owner of the type and quantity of steamed buns he wants."); //Call the wait method, discard the execution of the cpu, and enter the WAITING state (wait indefinitely) try { obj.wait(3000); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed buns are ready.,Customer 2 eats!"); System.out.println("---------------------------------------"); } } } }.start(); //Create a Boss Thread (Producer) new Thread(){ @Override public void run() { //Make steamed buns all the time while (true){ //It took five seconds to make steamed buns. try { Thread.sleep(5000);//Take 5 seconds to make steamed buns } catch (InterruptedException e) { e.printStackTrace(); } //Ensuring that there is only one thread to wait and wake up requires synchronization synchronized (obj){ System.out.println("The boss makes the steamed buns in five seconds,Inform customers,You can eat steamed buns."); //After making the steamed bun, call notify method to wake up the customer to eat the steamed bun. // obj.notify(); // If there are multiple waiting threads, wake up one at random obj.notifyAll(); //Wake up all waiting threads } } } }.start(); } }
Maybe the results don't seem logical, but here's just a demonstration: