Collaboration Fundamentals (wait/notify)
Java's root parent class is Object,java in the object class, not the thread class, and defines some basic methods of threading collaboration so that each object can invoke these methods, which have two types, one is wait and the other is notify.
There are two main wait methods:
Public final void Wait () throws Interruptedexceptionpublic final native void wait (long timeout) throws Interruptedexceptio N
One with a time parameter, in milliseconds, that represents a maximum wait for so long, with a parameter of 0 indicating an indefinite wait. One without a time parameter, indicating an indefinite wait, is actually called wait (0). The wait period can be interrupted, if interrupted, will throw interruptedexception.
What did wait actually do? Each object has a lock and a lock waiting queue, and when a thread enters the synchronized code block, it attempts to acquire the lock, and the current thread is added to the wait queue when it is not available. In fact, in addition to the wait queue for locks, each object has another wait queue, which represents the conditional queue, which is used for collaboration between threads. Calling wait will put the current thread on the condition queue and block it, indicating that the current thread is not executing, and that it needs to wait for a condition that it cannot change itself and requires other threads to change. When other threads change the condition, you should call the Notify method of the object:
Public final native void notify ();p ublic final native void Notifyall ();
What notify do is to select a thread from the conditional queue, remove it from the queue, and wake it up, and the difference between Notifyall and notify is that it removes all the threads in the condition queue and wakes them all up.
The Wait/notify method can only be called within a synchronized code block , and if the Wait/notify method is called, the current thread does not hold an object lock. Throws an exception java.lang.IllegalMonitorStateException.
The specific process for wait is:
-
- Puts the current thread in a conditional wait queue, frees the object lock , blocks the wait, and the thread state becomes waiting or timed_waiting
- Waits for time or is called by another thread to notify/notifyall from the condition queue, at which point the object lock is re-competed
-
- If a lock can be obtained, the thread state becomes runnable and returned from the wait call
- Otherwise, the thread joins the object lock waiting queue, the thread state becomes blocked, and only after the lock is obtained will it return from the wait call
When a thread returns from a wait call, the condition that does not represent its wait must be set up, and it needs to recheck its waiting condition, and the general invocation pattern is:
synchronized (obj) { while (condition not established) obj.wait (); // action after condition is satisfied }
Producer/Consumer model
Let's look at a producer and consumer example:
/** * @authorSilent Brother **/ Public classMyproducerconsumerdemo {Static classGoodsqueue {Private intsize; PrivateQueue<string> que =NewArraydeque<string>(); PublicGoodsqueue (intSize) {//maintain a bounded queue with the maximum capacity of the incoming queue Super(); This. Size =size; } Public synchronized voidPut (String e)throwsinterruptedexception { while(que.size () = =size) {System.out.println ("Queue is full, producer Waits"); Wait (); } que.add (e); System.out.println ("Producer Production:" +e); Notify (); } Public synchronizedString Take ()throwsinterruptedexception { while(que.size () = = 0) {System.out.println ("Queue is empty, consumer waits"); Wait (); } String e=Que.poll (); System.out.println ("Consumer consumption" +e); Notify (); returne; } } Static classProducerextendsThread {goodsqueue que; Random rad=NewRandom (); PublicProducer (goodsqueue que) {Super(); This. Que =que; } @Override Public voidrun () {inti = 0; Try { while(true) {String e=string.valueof (i); Que.put (e); I++; Thread.Sleep (Rad.nextint (1000));//producer Rest ready for next production } } Catch(Interruptedexception E1) {}}} Static classConsumerextendsThread {goodsqueue que; Random rad=NewRandom (); PublicConsumer (goodsqueue que) {Super(); This. Que =que; } @Override Public voidrun () {Try { while(true) {que.take (); Thread.Sleep (Rad.nextint (1000));//consumer rest ready to spend next time } } Catch(Interruptedexception e) {}}} Public Static voidMain (string[] args)throwsinterruptedexception {goodsqueue que=NewGoodsqueue (1); Producer Pro=NewProducer (que); Consumer Con=NewConsumer (que); Con.start (); Thread.Sleep (500); Pro.start (); }}
Threading basic collaboration and producer consumers