This time using Reentrantlock to implement the producer consumer model, the first reentrantlock, usually called a re-entry lock, so-called re-entry is a thread can again enter the lock has been held in the code block, the number of re-entry will be counted internally, when the count is 0, the lock is released. In fact, the Synchronized keyword represents the built-in lock, but also can be re-entered. But there are several differences:
1, Reentrantlock will locking and unlock to separate, can provide finer granularity of the addition of lock operation, built-in lock is basically a global lock (class, object, code block)
2, Reentrantlock provides the timing of the lock operation, which is built-in lock can not do.
3, Reentrantlock provides a polling lock operation, namely the Trylock () method, used in the loop, can reduce the thread scramble, reduce system calls and context switching, save resources, this is also built-in lock can not do.
Packagecom.smikevon.concurrent;Importjava.util.concurrent.locks.Condition;ImportJava.util.concurrent.locks.Lock;ImportJava.util.concurrent.locks.ReentrantLock; Public classproducerconsumer_05 { Public Static voidMain (string[] args) {FinalDrop drop =NewDrop (); NewThread (NewRunnable () { Public voidrun () {Try { NewProducer (drop). produce (); } Catch(interruptedexception e) {e.printstacktrace (); } } },Producers). Start (); NewThread (NewRunnable () { Public voidrun () {Try { NewConsumer (drop). consume (); } Catch(interruptedexception e) {e.printstacktrace (); } } },Consumers). Start (); } Static classproducer{Privatedrop drop; PublicProducer (Drop drop) { This. Drop =drop; } Public voidProduce ()throwsinterruptedexception{string[] Messages= { "I Am", "A programmer", "I'm very proud.", "Also very proud", "Dedication to love and hillock", "Diligence and Dedication", No regrets, "Dedication to Youth", "Hope by learning", Improve, Own, "Done", }; for(inti=0;i<messages.length;i++) {drop.put (messages[i]); } } } Static classconsumer{Privatedrop drop; PublicConsumer (Drop drop) { This. Drop =drop; } Public voidConsume ()throwsinterruptedexception{String Message= ""; Do{message=Drop.take (); } while(!message.equals ("Done")); } } Static classdrop{PrivateLock lock =NewReentrantlock (); //initialization condition is empty PrivateCondition empty =lock.newcondition (); //The condition is full, here is a full PrivateCondition full =lock.newcondition (); PrivateString message; Private BooleanIsexist =false ; Public voidPut (String message)throwsinterruptedexception{ while(true){ Try{lock.lock (); if(isexist) {full.await (); } This. Message =message; Isexist=true; Empty.signal (); System.out.println (Thread.CurrentThread (). GetName ()+":"+message); Break; }finally{lock.unlock (); } } } PublicString Take ()throwsinterruptedexception{ while(true){ Try{lock.lock (); if(!isexist) {empty.await (); } System.out.println (Thread.CurrentThread (). GetName ()+":"+message); Isexist=false; Full.signal (); return This. Message; }finally{lock.unlock (); } } } }}
Here are two condition, one indicating whether it is full, whether a representation is empty, giving practical meaning, if there are n threads, define n condition conditions. This way, when the signal () method is called, it is explicitly told which thread wakes from the waiting state and resumes the runnable state. Reduces the thread scramble lock brought on by the built-in lock Notifyall (), which consumes system resources when the system calls and the on-line switching are brought on by the scramble.
The first and second are the use of the original lock tool to implement the producer consumer model, in fact, the Java.util.concurrent package provides a number of convenient concurrency tools, these tools can be very convenient to implement the producer consumer model. such as Exchanger,semaphore and so on.
Java implementation of the producer consumer model (Implementation II)