Crazy Java Learning Notes ($)---------Thread collaboration

Source: Internet
Author: User

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

The following is an outline of this article directory:

A. Wait (), notify (), and Notifyall ()

Two. Condition

Three. Implementation of producer-consumer models

  

A. 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 was 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 A object ' s * Monitor by calling one of the wait methods */<span style= "color: #ff0000;" ><strong>public Final native void notify ();</strong></span>/** * wakes up all threads that is Waiti Ng on the This object ' s monitor. A * thread waits on a object ' s monitor by calling one of the * wait methods. */<span style= "color: #ff0000;" ><strong>public final native void Notifyall ();</strong></span>/** * Causes the current thread to Wai t until either another thread invokes the * {@link java.lang.object#notify ()} method or the * {@link java.lang.object#no  Tifyall ()} method for this object, or a * specified amount of time have elapsed. * <p> * The current thread must own this object ' s MonitoR. */<span style= "color: #ff0000;" ><strong>public final native void wait (long timeout) throws Interruptedexception;</strong></span >

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) The Wait () method that invokes an object can cause the current thread to block, and the current thread must have a monitor (that is, a lock) on this object

3) Invoking an object's Notify () method 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 class Test {public static Object object = new Object ();        public static void Main (string[] args) {Thread1 thread1 = new Thread1 ();                 Thread2 thread2 = new Thread2 ();                 Thread1.start ();        try {thread.sleep (200);        } catch (Interruptedexception e) {e.printstacktrace ();    } thread2.start (); } static class Thread1 extends thread{@Override public void Run () {synchronized (objec                T) {try {object.wait (); } catch (Interruptedexception e) {} System.out.println ("Thread" +thread.currentthread (). GetName (            ) + "acquired to lock"); }}}} Static class Thread2 extends thread{@Override public void Run () {SYNCHR                Onized (object) {object.notify (); SYSTEM.OUT.PRINTLN ("Thread" +thread.currentthread (). GetName () + "called Object.notify ()");        } System.out.println ("Thread" +thread.currentthread (). GetName () + "release lock"); }    }}

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

Thread thread-1 called the object.notify () thread-1 freed the lock thread-0 gets to the lock
two. Condition

Condition is only present in Java 1.5, which is used instead of the traditional object's Wait (), notify () to achieve collaboration between threads, compared to wait (), notify () with object, Using Condition1 's await (), signal () is a way to make collaboration between threads more secure and efficient . 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 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.

three. Implementation of producer-consumer models

1. Use the Wait () and notify () of object to implement:

public class Test {private int queuesize = 10;          Private priorityqueue<integer> queue = new priorityqueue<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 ();        } class Consumer extends thread{@Override public void Run () {consume ();                    } private void Consume () {while (true) {synchronized (queue) {                            while (queue.size () = = 0) {try {System.out.println ("queue empty, wait for data");                        Queue.wait ();                            } catch (Interruptedexception e) {e.printstacktrace ();                        Queue.notify ();                }                    }    Queue.poll ();                    Each removal of the first element of the team queue.notify ();                System.out.println ("Take an element from the queue, queue remaining" +queue.size () + "elements");             }}}} class Producer extends thread{@Override public void run () {        Produce ();                    } private void produce () {while (true) {synchronized (queue) { while (queue.size () = = Queuesize) {try {System.out.println ("queue full, waiting for free                            Space ");                        Queue.wait ();                            } catch (Interruptedexception e) {e.printstacktrace ();                        Queue.notify ();        }} queue.offer (1);                    Insert one element at a time queue.notify ();                SYSTEM.OUT.PRINTLN ("Inserts an element into the queue, the remaining space of the queue:" + (Queuesize-queue.size ()));       }     }        }    }} 

2. Using condition to implement

public class Test {private int queuesize = 10;    Private priorityqueue<integer> queue = new priorityqueue<integer> (queuesize);    Private lock lock = new Reentrantlock ();    Private Condition Notfull = Lock.newcondition ();         Private Condition 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 ();        } class Consumer extends thread{@Override public void Run () {consume ();                private void Consume () {while (true) {Lock.lock (); try {while (queue.size () = = 0) {try {System.out.prin                            TLN ("Queue empty, waiting for data");                        Notempty.await (); } catch (InterruptedexcePtion e) {e.printstacktrace ();                }} queue.poll ();                    Each removal of the first element of the team notfull.signal ();                System.out.println ("Take an element from the queue, queue remaining" +queue.size () + "elements");                } finally{Lock.unlock ();             }}}} class Producer extends thread{@Override public void run () {        Produce ();                private void produce () {while (true) {Lock.lock (); try {while (queue.size () = = Queuesize) {try {System.                            Out.println ("Queue full, waiting for free space");                        Notfull.await ();                        } catch (Interruptedexception e) {e.printstacktrace ();     }} queue.offer (1);   Insert one element at a time notempty.signal ();                SYSTEM.OUT.PRINTLN ("Inserts an element into the queue, the remaining space of 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

If there are any shortcomings please understand, and welcome criticism.

This paper draws on:

Http://www.cnblogs.com/dolphin0520/p/3920385.html

Crazy Java Learning Notes ($)---------Thread collaboration

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.