1.Condition Introduction
The role of condition is to control the lock more precisely. The await () method in condition is equivalent to the wait () method of object, and the signal () method in condition is equivalent to the Notify () method of object, condition in Signalall () The Notifyall () method equivalent to object. The difference is that the wait (), notify (), and Notifyall () methods in object are used in bundles with the "Sync lock" (synchronized keyword), whereas condition is required with a "mutex"/"shared lock" bundle.
2.Condition Function List
//causes the current thread to wait until it receives a signal or is interrupted. voidawait ()//causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. BooleanAwaitLongTime , timeunit unit)//causes the current thread to wait until it receives a signal, is interrupted, or arrives at a specified wait time. LongAwaitnanos (Longnanostimeout)//causes the current thread to remain in a wait state until it receives a signal. voidawaituninterruptibly ()//causes the current thread to wait until it receives a signal, is interrupted, or reaches a specified deadline. BooleanAwaituntil (Date deadline)//wakes up a waiting thread. voidsignal ()//wakes all waiting threads. voidSignalall ()
3.Condition Example
(1) To demonstrate thread hibernation/wake through the Wait () of object, notify ()
(2) The Sleep/wake function of the thread is demonstrated through condition's await (), signal ().
(3) is the advanced function through condition.
Example 1:
Public classTesthello { Public Static voidMain (string[] args) {Threada ta=NewThreada ("Ta"); synchronized(TA) {//acquisition of "Object TA synchronization Lock" via synchronized (TA) Try{System.out.println (Thread.CurrentThread (). GetName ()+ "Start Ta"); Ta.start (); System.out.println (Thread.CurrentThread (). GetName ()+ "Block"); Ta.wait (); //waitSystem.out.println (Thread.CurrentThread (). GetName ()+ "Continue"); } Catch(interruptedexception e) {e.printstacktrace (); } } } Static classThreadaextendsthread{ PublicThreada (String name) {Super(name); } Public voidrun () {synchronized( This) {//get "synchronization lock for current object" via synchronized (this)System.out.println (Thread.CurrentThread (). GetName () + "Wakup others"); Notify (); //wake "Waiting thread on current object" } } }}
Example 2:
ImportJava.util.concurrent.locks.Lock;Importjava.util.concurrent.locks.Condition;ImportJava.util.concurrent.locks.ReentrantLock; Public classConditionTest1 {Private StaticLock lock =NewReentrantlock (); Private StaticCondition Condition =lock.newcondition (); Public Static voidMain (string[] args) {Threada ta=NewThreada ("Ta"); Lock.lock (); //Get lock Try{System.out.println (Thread.CurrentThread (). GetName ()+ "Start Ta"); Ta.start (); System.out.println (Thread.CurrentThread (). GetName ()+ "Block"); Condition.await (); //waitSystem.out.println (Thread.CurrentThread (). GetName ()+ "Continue"); } Catch(interruptedexception e) {e.printstacktrace (); } finally{lock.unlock (); //Release Lock } } Static classThreadaextendsthread{ PublicThreada (String name) {Super(name); } Public voidrun () {lock.lock (); //Get lock Try{System.out.println (Thread.CurrentThread (). GetName ()+ "Wakup Others"); Condition.signal (); //Wake up "Other threads where the condition is locked"}finally{lock.unlock (); //Release Lock } } }}
Condition:
In addition to supporting the above features, condition is more powerful in that it can control the sleep and wake of multiple threads more finely. For the same lock, we can create multiple condition and use different condition in different situations.
For example, if the multithreading reads/writes the same buffer: when the data is written to the buffer, the "read thread" is awakened, the "Write thread" is awakened after the data is read from the buffer, and the "Write thread" waits when the buffer is full, and the "read thread" waits when the buffer is empty. If wait () in the object class is used, notify (), Notifyall () implements the buffer, it is not possible to wake "read threads" with explicit specified notify () or Notifyall () when the data is written to the buffer, You can only wake all threads through Notifyall (but Notifyall cannot distinguish whether the thread that wakes up is a read thread or a write thread). However, by condition, you can explicitly specify the wake-up read thread.
classBoundedbuffer {FinalLock lock =NewReentrantlock (); FinalCondition Notfull =lock.newcondition (); FinalCondition Notempty =lock.newcondition (); Finalobject[] Items =NewObject[5]; intputptr, Takeptr, Count; Public voidPut (Object x)throwsinterruptedexception {lock.lock (); //Get lock Try { //if the buffer is full, wait until the buffer is not full before adding X to the buffer. while(Count = =items.length) notfull.await (); //adding x to the bufferITEMS[PUTPTR] =x; //set the put statistic to putptr+1, or putptr to 0 if buffer is full. if(++putptr = = items.length) putptr = 0; //The number of buffers is +1++count; //Wake the take thread because the take thread waits through notempty.await ()notempty.signal (); //Print the data that is writtenSystem.out.print (Thread.CurrentThread (). GetName () + "put"); for(inti = 0; i < items.length; i++) {System.out.print (Items[i]+ " "); } System.out.println ("\ n"); } finally{lock.unlock (); //Release Lock } } PublicObject Take ()throwsinterruptedexception {lock.lock (); //Get lock Try { //if the buffer is empty, wait until the buffer is not empty, and the x is removed from the buffer. while(count = = 0) notempty.await (); //take x out of the bufferObject x =Items[takeptr]; ITEMS[TAKEPTR]=NULL; //"Take statistics takeptr+1" and if "buffer is empty", set Takeptr to 0. if(++takeptr = = items.length) takeptr = 0; //number of "buffers"-1--count; //wake up the put thread because the put thread waits through notfull.await ()notfull.signal (); //print out the dataSystem.out.print (Thread.CurrentThread (). GetName () + "Take"); for(inti = 0; i < items.length; i++) {System.out.print (Items[i]+ " "); } System.out.println ("\ n"); returnx; } finally{lock.unlock (); //Release Lock } }} Public classTesthello {Private StaticBoundedbuffer BB =NewBoundedbuffer (); Static classPutthreadextendsThread {Private intnum; PublicPutthread (String name,intnum) { Super(name); This. num =num; } Public voidrun () {Try{Thread.Sleep (1);//Thread hibernation 1msBb.put (num);//writing data to Boundedbuffer}Catch(Interruptedexception e) {}}} Static classTakethreadextendsThread { PublicTakethread (String name) {Super(name); } Public voidrun () {Try{Thread.Sleep (10);//Thread hibernation 1msInteger num = (integer) bb.take ();//extracting data from the Boundedbuffer}Catch(Interruptedexception e) {}}} Public Static voidMain (string[] args) {//start 10 "Write Threads" and write data to Boundedbuffer continuously (write 0-9);//start 10 "Read Threads" and read the data continuously from the Boundedbuffer. for(inti=0; i<10; i++) { NewPutthread ("P" +I, I). Start (); NewTakethread ("T" +i). Start (); } }}
Result Description:
(1) Boundedbuffer is a buffer with a capacity of 5, the buffer is stored in the object, support multi-threaded read/write buffer. When multiple threads manipulate "one Boundedbuffer object", they mutually exclusive access to the buffer items through the mutex lock, and all threads under the same Boundedbuffer object share "Notfull" and "Notempty" These two condition.
The notfull is used to control write buffering, and Notempty is used to control read buffering. When the buffer is full, the thread that calls put will execute notfull.await () to wait, when the buffer is not full, add the object to the buffer and count+1 the buffer capacity, and finally, call Notempty.signal () Buffer the waiting thread on the Notempty (calling Notempty.await's thread). In short, notfull controls "write to buffer" and wakes the waiting thread on notempty after writing data to the buffer.
Similarly, notempty controls "read buffer", which wakes the waiting thread on Notfull when the buffer data is read.
(2) in the main function of ConditionTest2, 10 "Write Threads" are started, and the data is continuously written to Boundedbuffer, and 10 "read Threads" are started, and the data is continuously read from Boundedbuffer.
Multithreaded programming--condition condition of part 5.2 Juc lock