Java concurrent Programming: two ways to collaborate between threads: Wait, notify, notifyall, and condition

Source: Internet
Author: User
Tags object object thread class

Tag: Hose ack Time decides to synchronize trace information about comparison

Original link Java concurrent programming: two ways to collaborate between threads: Wait, notify, notifyall, and condition

In the front we will have a lot of questions about synchronization, but in reality, there is a need for collaboration between threads. For example, the most classic producer-consumer model: When the queue is full, the producer needs to wait for the queue to have space to continue to put the goods inside, and during the waiting period, the producer must release the seizure rights to the critical resource (that is, the queue). Because producers do not release the use of critical resources, consumers will not be able to consume the goods in the queue, there is no space for the queue, then the producers have been waiting indefinitely. Therefore, in general, when the queue is full, the producer will be handed over to the critical resources of the occupation, and into the suspended state. Then wait for the consumer to consume the goods, and then the consumer informs the producer that the queue has space. Similarly, when the queue is empty, the consumer must wait, waiting for the producer to notify it that there is a product in the queue. This process of communicating with each other is a collaboration between threads.

Today we're going to explore two of the most common ways in which Java threads work together: Using Object.wait (), object.notify (), and using condition.

Wait (), notify (), and Notifyall ()

Wait (), notify (), and Notifyall () are methods in the object class:

/*** wakes up a single thread that's waiting on this object ' s* Monitor. If any threads is waiting on the This object, one of the them* is chosen to be awakened. The choice is arbitrary and occurs at* The discretion of the implementation. A thread waits on an object ' s* Monitor by calling one of the wait methods */ Public Final native void Notify();/*** wakes up all threads is waiting on this object ' s monitor. A* thread waits on a object ' s monitor by calling one of the* Wait methods. */ Public Final native void Notifyall();/*** Causes the current thread to wait until either another thread invokes the * {@link java.lang.object#notify ()}method or the * {@link java.lang.object#notifyall ()}method for this object, or a* Specified amount of time has elapsed.* <p>* The current thread is must own this object ' s monitor. */Public final native void wait (long timeout) throws interruptedexception;

The following information can be found from the text descriptions of these three methods:

1. The wait (), notify (), and Notifyall () methods are local methods and are final methods and cannot be overridden.

2. Calling the Wait () method of an object can cause the current thread to block, and the current thread must have the monitor (that is, the lock) of this object

3. Invoking the Notify () method of an object wakes up a thread waiting for the object's monitor, and if more than one thread waits for the object's monitor, only one of the threads can be awakened;

4. Call the Notifyall () method to wake up all the threads that are waiting for this object's monitor;

A friend may have questions about why these three are not methods in the thread class declaration, but rather methods declared in the object class (since the thread class inherits the object class, so thread can also call three methods)? In fact, the problem is simple, because each object has a monitor (that is, lock), so the current thread to wait for an object's lock, of course, this object should be manipulated. Instead of using the current thread, the current thread may be waiting for locks on multiple threads, which can be very complex if manipulated by a thread.

As mentioned above, if you call the Wait () method of an object, the current thread must have the monitor (that is, the lock) of the object, so calling the wait () method must be done either in a synchronous block or in a synchronous method (synchronized block or Synchronized method).

Calling the Wait () method of an object is equivalent to having the current thread hand over the object's monitor, then going into a wait state, waiting for a subsequent lock on the object (the sleep method in the thread class causes the current thread to suspend execution for a period of time, allowing other threads to continue to execute. But it does not release the object lock);

The Notify () method wakes up a thread that is waiting for the object's monitor, and when there are multiple threads waiting for the object's monitor, only one of the threads can be woken up, and it is unclear which thread to wake.

Similarly, the Notify () method of an object is called, and the current thread must have the monitor for that object, so calling the Notify () method must be done either in a synchronous block or in a synchronous method (synchronized block or Synchronized method).

The Nofityall () method can wake all threads that are waiting for the object's monitor, which is different from the Notify () method.

One thing to note here: the Notify () and Notifyall () methods simply wake up the thread that waits for the object's monitor, and do not determine which thread can get to monitor.

As a simple example: if there are three threads Thread1, Thread2, and Thread3 waiting for the monitor of the object Objecta, THREAD4 has the monitor of the object objecta, When the Objecta.notify () method is called in Thread4, only one of Thread1, Thread2, and Thread3 can be awakened. Note that being awakened does not mean that the OBJECTA Monitor is acquired immediately. If the Objecta.notifyall () method is called in Thread4, the three threads of Thread1, Thread2, and Thread3 will be awakened. As for which thread is next able to get to objecta monitor, it depends on the operating system's schedule.

In particular, it is important to note that a thread being awakened does not represent a monitor that immediately acquires the object, but only when the Notify () or Notifyall () is called and exits the synchronized block, and the remaining threads can get lock execution after the object lock is released.

Let's take a look at the following example:

 Public classTest { Public StaticObject object =NewObject (); Public Static void Main(string[] args) {Thread1 Thread1 =New Thread1(); Thread2 thread2 =New Thread2(); Thread1.Start();Try{Thread.Sleep( $); }Catch(Interruptedexception e) {e.Printstacktrace(); } thread2.Start(); }Static classThread1extendsthread{@Override         Public void Run() {synchronized(object) {Try{object.}wait(); }Catch(Interruptedexception e) {} System. out.println("Threads"+thread.CurrentThread().GetName()+"Get the lock."); }        }    }Static classThread2extendsthread{@Override         Public void Run() {synchronized(object) {object.}Notify(); System. out.println("Threads"+thread.CurrentThread().GetName()+"Object.notify ()" was called); } System. out.println("Threads"+thread.CurrentThread().GetName()+"Release the lock."); }    }}

No matter how many times it runs, the result must be:

线程Thread-1调用了object.notify()线程Thread-1释放了锁线程Thread-0获取到了锁
Condition

Condition is only present in Java 1.5, it is used to replace the traditional object of Wait (), notify () to implement the collaboration between threads, compared to the Wait (), notify () using object, and the Condition1 await () , signal () is a more secure and efficient way to collaborate between threads. Therefore, it is generally recommended to use the condition, as described in the blocking Queue blog post, where the blocking queue is actually using condition to simulate inter-threading collaboration.

    • Condition is an interface, the basic method is the await () and the signal () method;
    • Condition relies on the lock interface, generating a condition base code that is lock.newcondition ();
    • The await () and signal () methods that call condition must be within lock protection, meaning they must be used between Lock.lock () and Lock.unlock.

Await () in Conditon corresponds to the Wait () of object;

The signal () in condition corresponds to the Notify () of the object;

The Signalall () in condition corresponds to the Notifyall () of the object.
  

Implementation of the producer-consumer model using the Wait () and notify () of object
 Public classTest {Private intQueuesize =Ten;Privatepriorityqueue<integer> queue =NewPriorityqueue<integer> (queuesize); Public Static void Main(string[] args) {Test test =New Test(); Producer Producer = Test.New Producer(); Consumer Consumer = Test.New Consumer(); Producer.Start(); Consumer.Start(); }classConsumerextendsthread{@Override         Public void Run() {Consume(); }Private void Consume() { while(true){synchronized(queue) { while(Queue.size() ==0){Try{System. out.println("Queue empty, waiting for data"); Queue.wait(); }Catch(Interruptedexception e) {e.Printstacktrace(); Queue.Notify(); }} queue.Poll();//Remove the first element of the team each timeQueue.Notify(); System. out.println("Take an element from the queue, the queue remains"+queue.size()+"Elements"); }            }        }    }classProducerextendsthread{@Override         Public void Run() {Produce(); }Private void Produce() { while(true){synchronized(queue) { while(Queue.size() = = Queuesize) {Try{System. out.println("The queue is full, waiting for free space"); Queue.wait(); }Catch(Interruptedexception e) {e.Printstacktrace(); Queue.Notify(); }} queue. Offer(1);//Insert one element at a timeQueue.Notify(); System. out.println("Insert an element into the queue and the remaining space in the queue:"+ (Queuesize-queue.size())); }            }        }    }}
Using the condition implementation
 Public classTest {Private intQueuesize =Ten;Privatepriorityqueue<integer> queue =NewPriorityqueue<integer> (queuesize);PrivateLock lock =NewReentrantlock ();PrivateCondition Notfull = lock.newcondition();PrivateCondition Notempty = lock.newcondition(); Public Static void Main(string[] args) {Test test =New Test(); Producer Producer = Test.New Producer(); Consumer Consumer = Test.New Consumer(); Producer.Start(); Consumer.Start(); }classConsumerextendsthread{@Override         Public void Run() {Consume(); }Private void Consume() { while(true) {lock.Lock();Try{ while(Queue.size() ==0){Try{System. out.println("Queue empty, waiting for data"); Notempty.await(); }Catch(Interruptedexception e) {e.Printstacktrace(); }} queue.Poll();//Remove the first element of the team each timeNotfull.Signal(); System. out.println("Take an element from the queue, the queue remains"+queue.size()+"Elements"); }finally{lock.Unlock(); }            }        }    }classProducerextendsthread{@Override         Public void Run() {Produce(); }Private void Produce() { while(true) {lock.Lock();Try{ while(Queue.size() = = Queuesize) {Try{System. out.println("The queue is full, waiting for free space"); Notfull.await(); }Catch(Interruptedexception e) {e.Printstacktrace(); }} queue. Offer(1);//Insert one element at a timeNotempty.Signal(); System. out.println("Insert an element into the queue and the remaining space in the queue:"+ (Queuesize-queue.size())); }finally{lock.Unlock(); }            }        }    }}
Resources
    • The idea of Java programming
    • http://blog.csdn.net/ns_code/article/details/17225469
    • http://blog.csdn.net/ghsau/article/details/7481142

Java concurrent Programming: two ways to collaborate between threads: Wait, notify, notifyall, and condition

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.