1 // The standard idiom for calling the wait 2 synchronized (sharedobject) {3 while (condition) {4 sharedobject.wait (); releases lock, and reacquires on Wake up5 }6 // do action based upon condition e.g. take or put to queue 7 }
Canonical code template using the wait and notify functions.
The purpose of using wait in the while loop is to check whether the condition is satisfied before and after the thread is awakened, and if the condition is not changed, the wake-up notification of the Notify before wait is invoked, which is not guaranteed to be awakened, and the pit will cause a deadlock problem.
1 Public classProducerconsumer {2 Public Static voidMain (String args[]) {3queue<integer> buffer =NewLinkedlist<>();4 intMaxSize = 10;5Thread producer =NewProducer (buffer, maxSize, "Producer"); 6Thread consumer =NewProducer (buffer, maxSize, "CONSUMER");7 Producer.start ();8 Consumer.start ();9 } Ten}
In the above code, a linkedlist is declared as a buffer queue (in Java, LinkedList implements the interface of the queue).
classProducerextendsThread {PrivateQueue<integer>queue; Private intmaxSize; PublicProducer (queue<integer> Queue,intmaxSize, String name) { Super(name); This. Queue =queue; This. maxSize =maxSize; } @Override Public voidrun () { while(true) { synchronized(queue) { //Other threads cannot change this queue while we are checking conditions while(queue.size () = =maxSize) { Try { //Queue is full//Producer thread waiting for//consumer to take something from queuequeue.wait (); } Catch(Exception e) {e.printstacktrace (); } Random Random=NewRandom (); intProducervalue =Random.nextint (); Queue.add (Producervalue); Queue.notifyall (); } } } }}
If the code is a producer, it continues to insert random integers into the linkedlist in an infinite loop until the LinkedList is full. If the queue is full, the producer thread consumes any integer in the queue and waits for the producer thread before the consumer thread notify.
1 classConsumerextendsThread {2 PrivateQueue<integer>queue;3 Private intmaxSize;4 PublicConsumer (queue<integer> Queue,intmaxSize, String name) {5 Super(name);6 This. Queue =queue; 7 This. maxsize=maxSize; 8 } 9 @OverrideTen Public voidrun () { One while(true) { A synchronized(queue) { - while(Queue.isempty ()) { - //queue is empty; the //Consumer thread is waiting - //For producer thread to put something in queue - Try { - queue.wait (); +}Catch(Exception e) { - e.printstacktrace (); + } APrint ("Consumer value:" +Queue Remove ()); at Queue.notifyall (); - } - } - } - } -}
Attention:
1. You can use the wait and notify functions to implement inter-thread communication, which you can use to achieve communication between multiple threads.
2. Always use wait, notify, notifyall in synchronized functions or objects, otherwise Java Virtual opportunity generates illgalmonitorstateexception.
3. Always use wait in the while loop instead of the IF statement, so that the loop checks for wait conditions before and after the thread sleeps, and processes the wake-up notification if the condition does not actually change.
4. Always use wait on objects that are shared between multiple threads (the buffer queue in the producer consumer model).
Producer-consumer Pattern:
Consumer:
sunchronized (obj) { while ( ! Worktodo) { obj.wait (); } // Get next item from the This queue false ;} // Do work on the item
Producer:
1 synchronized (obj) {2 if (! Worktodo) {3 // Add work to queue4 true; 5 }6 obj.notifyall (); 7 }
Java Producer Mode Consumer model