Hello everyone, the previous article introduces some basic ways of communication and collaboration between threads, so this article will introduce the classic wait-notify mechanism.
What is the wait-notify mechanism?
Imagine that there are two threads a, B, if the business scenario requires that the two threads alternately perform the task (for example, a after performing a task after the B execution, b after the execution of a and then a to perform such repeated alternating), the previous basic communication method can only let the thread pause for a specified time, The Join method is also unable to do this kind of alternating execution requirements, how to do?
Don't worry, for this scenario, Java also provides us with a classic thread communication mode--wait-notify mechanism, which involves the following three methods (the knowledge of the lock will be described in detail):
Wait method: The current thread calls the wait method to let the current thread hold the object lock so that other threads can get it, and then the current thread stops executing and enters the waiting state. The current thread continues to attempt to acquire an object lock until the wake-up or interrupt signal is received. If you get the object lock successfully at this point, you can continue to perform the task.
Notify method: The task of the current thread is about to execute and a wake-up signal is sent, and only the thread that receives the wake-up signal attempts to acquire the object lock. Of course, the possibility of acquiring an object lock may fail because the Notify method does not immediately release the lock, but rather waits until the thread finishes executing to actually release the lock.
Notifyall method: Similar to the Notify method, the only difference is that the method will emit a wake-up signal to all current threads waiting for this object lock. As to which thread eventually grabs the object lock, it depends on which thread is "lucky".
There are two points to follow about these methods:
1.wait, notify, Notifyall these three methods are defined in the object class, and the object class is the parent class of all classes, so all objects in Java inherit these three methods.
2. These three methods must be called in the synchronization block (then the synchronization blocks are introduced), and Java throws the java.lang.IllegalMonitorStateException exception if the three methods are called outside of the synchronization block.
Single-producer-single-consumer model based on wait-notify mechanism
The above has introduced the methods used by the wait-notify mechanism and the points needing attention, in fact, for this mechanism, there is a very famous, very classic model-producer consumer model.
What is a producer-consumer model? In a nutshell, there are two types of threads, the producer thread and the consumer thread, and a fixed-size resource queue.
The task of the producer is to produce the product according to the raw material, and to throw the good product into the queue; The consumer's task is to take the product that has been produced in the queue to carry out the packing.
We can see in this scenario, because the queue can accommodate a limited number of resources, so when the queue is full, the producer will not be able to continue to put products in the queue, the producer will need to wait for the consumer to take the product from the queue, to continue to put products in the queue;
And the consumer is the same, when the queue is empty, consumers can not get the product from the queue, it is necessary to wait for the producers to successfully produce products and throw in the queue, in order to continue to take products from the queue.
This scenario is the most suitable scenario for the wait-notify mechanism, and here is a single-producer-single-Consumer analog code:
1 /**2 * Single producer-consumer model based on the wait-notify mechanism3 */4 Public classProducerandconsumer {5 6 Public Static voidMain (string[] args) {7Resource Resource =NewResource ();8 //Producer Threads9Producerthread P1 =NewProducerthread (Resource);Ten //Consumer Threads OneConsumerthread C1 =NewConsumerthread (Resource); A - P1.start (); - C1.start (); the - } - } - + - /** + * Public Resources category A * @author at * - */ - classresource{//Important - //Current number of resources - Private intnum = 0; - //number of resources allowed in the resource pool in Private intSize = 10; - to /** + * Take resources away from the resource pool - */ the Public synchronized voidRemove () { * if(num > 0){ $num--;Panax NotoginsengSYSTEM.OUT.PRINTLN ("Consumer" + thread.currentthread (). GetName () + -"Consumes one piece of resources," + "Current thread pool has" + num + "); theNotifyall ();//informing producers of production resources +}Else{ A Try { the //If there is no resource, the consumer enters the wait state + wait (); -SYSTEM.OUT.PRINTLN ("Consumer" + thread.currentthread (). GetName () + "thread into wait state"); $}Catch(interruptedexception e) { $ e.printstacktrace (); - } - } the } - /**Wuyi * Add resources to the resource pool the */ - Public synchronized voidAdd () { Wu if(Num <size) { -num++; AboutSystem.out.println ("producer" + Thread.CurrentThread (). GetName () + "production of one piece of resources, current resource pool has" $+ num + "single"); - //notify the waiting consumer - Notifyall (); -}Else{ A //If there are 10 resources in the current resource pool + Try{ theWait ();//The producer enters the waiting state and releases the lock -System.out.println (Thread.CurrentThread (). GetName () + "thread into Wait"); $}Catch(interruptedexception e) { the e.printstacktrace (); the } the } the } - } in the the /** About * Consumer Thread the */ the classConsumerthreadextendsthread{ the PrivateResource Resource; + PublicConsumerthread (Resource Resource) { - This. Resource =resource; the }Bayi @Override the Public voidrun () { the while(true){ - Try { -Thread.Sleep (1000); the}Catch(interruptedexception e) { the e.printstacktrace (); the } the Resource.remove (); - } the } the } the 94 the /** the * Producer Threads the */98 classProducerthreadextendsthread{ About PrivateResource Resource; - PublicProducerthread (Resource Resource) {101 This. Resource =resource;102 }103 @Override104 Public voidrun () { the //continuous production of resources106 while(true){107 Try {108Thread.Sleep (1000);109}Catch(interruptedexception e) { the e.printstacktrace ();111 } the Resource.add ();113 } the } the the}
View Code
Children's shoes can run the code to try, here the maximum number of resources pool allowed to put 10 products.
Here's a question for everyone to think about, if my add and remove methods here do not add synchronized adornments, Throws a Java.lang.IllegalMonitorStateException exception, what causes Java to do so? I will announce the answer when I introduce the Synchronized keyword.
Well, the wait-notify mechanism here is complete, I hope you can understand. The following article will explain the use of the keyword volatile.
--wait-notify mechanism of inter-thread communication and collaboration mode