UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

421 lines (405 loc) 56.2 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"><head><title>Synchronization</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Synchronization"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-9-SECT-3"/>Synchronization</h1></div></div></div><p><a id="I_indexterm9_id716144" class="indexterm"/>Every thread has a mind of its own. Normally, a thread goes about its business without any regard for what other threads in the application are doing. Threads may be time-sliced, which means they can run in arbitrary spurts and bursts as directed by the operating system. On a multiprocessor system, it is even possible for many different threads to be running simultaneously on different CPUs. This section is about coordinating the activities of two or more threads so that they can work together and not collide in their use of the same variables and methods (coordinating their play on the golf course).</p><p>Java provides a few simple structures for synchronizing the activities of threads. They are all based on the concept of monitors, a widely used synchronization scheme. You don’t have to know the details about how monitors work to be able to use them, but it may help you to have a picture in mind.</p><p><a id="I_indexterm9_id716164" class="indexterm"/>A monitor is essentially a lock. The lock is attached to a resource that many threads may need to access, but that should be accessed by only one thread at a time. It’s very much like a restroom with a lock on the door; if it’s unlocked, you can enter and lock the door while you are using it. If the resource is not being used, the thread can acquire the lock and access the resource. When the thread is done, it relinquishes the lock, just as you unlock the restroom door and leave it open for the next person. However, if another thread already has the lock for the resource, all other threads must wait until the current thread is done and has released the lock. This is just like when the restroom is occupied when you arrive: you have to wait until the current user is done and unlocks the door.</p><p>Fortunately, Java makes the process of synchronizing access to resources fairly easy. The language handles setting up and acquiring locks; all you need to do is specify the resources that require synchronization.</p><div class="sect2" title="Serializing Access to Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-9-SECT-3.1"/>Serializing Access to Methods</h2></div></div></div><p><a id="I_indexterm9_id716190" class="indexterm"/> <a id="idx10502" class="indexterm"/>The most common need for synchronization among threads in Java is to serialize their access to some resource (an object)—in other words, to make sure that only one thread at a time can manipulate an object or variable.<sup>[<a id="learnjava3-CHP-9-FNOTE-2" href="#ftn.learnjava3-CHP-9-FNOTE-2" class="footnote">26</a>]</sup> In Java, every object has an associated lock. To be more specific, every class and every instance of a class has its own lock. The <a id="I_indexterm9_id716236" class="indexterm"/><code class="literal">synchronized</code> keyword marks places where a thread must acquire the lock before proceeding.</p><p>For example, suppose we implemented a <code class="literal">SpeechSynthesizer</code> class that contains a <code class="literal">say()</code> method. We don’t want multiple threads calling <code class="literal">say()</code> at the same time because we wouldn’t be able to understand anything being said. So we mark the <code class="literal">say()</code> method as <code class="literal">synchronized</code>, which means that a thread must acquire the lock on the <code class="literal">SpeechSynthesizer</code> object before it can speak:</p><a id="I_9_tt499"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">SpeechSynthesizer</code> <code class="o">{</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">say</code><code class="o">(</code> <code class="n">String</code> <code class="n">words</code> <code class="o">)</code> <code class="o">{</code> <code class="c1">// speak</code> <code class="o">}</code> <code class="o">}</code></pre><p>Because <code class="literal">say()</code> is an instance method, a thread must acquire the lock on the <code class="literal">SpeechSynthesizer</code> instance it’s using before it can invoke the <code class="literal">say()</code> method. When <code class="literal">say()</code> has completed, it gives up the lock, which allows the next waiting thread to acquire the lock and run the method. It doesn’t matter whether the thread is owned by the <code class="literal">SpeechSynthesizer</code> itself or some other object; every thread must acquire the same lock, that of the <code class="literal">SpeechSynthesizer</code> instance. If <code class="literal">say()</code> were a class (static) method instead of an instance method, we could still mark it as <code class="literal">synchronized</code>. In this case, because no instance object is involved, the lock is on the class object itself.</p><p>Often, you want to synchronize multiple methods of the same class so that only one method modifies or examines parts of the class at a time. All static synchronized methods in a class use the same class object lock. By the same token, all instance methods in a class use the same instance object lock. In this way, Java can guarantee that only one of a set of synchronized methods is running at a time. For example, a <code class="literal">SpreadSheet</code> class might contain a number of instance variables that represent cell values as well as some methods that manipulate the cells in a row:</p><a id="I_9_tt500"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">SpreadSheet</code> <code class="o">{</code> <code class="kt">int</code> <code class="n">cellA1</code><code class="o">,</code> <code class="n">cellA2</code><code class="o">,</code> <code class="n">cellA3</code><code class="o">;</code> <code class="kd">synchronized</code> <code class="kt">int</code> <code class="nf">sumRow</code><code class="o">()</code> <code class="o">{</code> <code class="k">return</code> <code class="n">cellA1</code> <code class="o">+</code> <code class="n">cellA2</code> <code class="o">+</code> <code class="n">cellA3</code><code class="o">;</code> <code class="o">}</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">setRow</code><code class="o">(</code> <code class="kt">int</code> <code class="n">a1</code><code class="o">,</code> <code class="kt">int</code> <code class="n">a2</code><code class="o">,</code> <code class="kt">int</code> <code class="n">a3</code> <code class="o">)</code> <code class="o">{</code> <code class="n">cellA1</code> <code class="o">=</code> <code class="n">a1</code><code class="o">;</code> <code class="n">cellA2</code> <code class="o">=</code> <code class="n">a2</code><code class="o">;</code> <code class="n">cellA3</code> <code class="o">=</code> <code class="n">a3</code><code class="o">;</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>In this example, methods <code class="literal">setRow()</code> and <code class="literal">sumRow()</code> both access the cell values. You can see that problems might arise if one thread were changing the values of the variables in <code class="literal">setRow()</code> at the same moment another thread was reading the values in <code class="literal">sumRow()</code>. To prevent this, we have marked both methods as <code class="literal">synchronized</code>. When threads are synchronized, only one runs at a time. If a thread is in the middle of executing <code class="literal">setRow()</code> when another thread calls <code class="literal">sumRow()</code>, the second thread waits until the first one finishes executing <code class="literal">setRow()</code> before it runs <code class="literal">sumRow()</code>. This synchronization allows us to preserve the consistency of the <code class="literal">SpreadSheet</code>. The best part is that all this locking and waiting is handled by Java; it’s invisible to the programmer.</p><p>In addition to synchronizing entire methods, the <a id="I_indexterm9_id716443" class="indexterm"/><code class="literal">synchronized</code> keyword can be used in a special construct to guard arbitrary blocks of code. In this form, it also takes an explicit argument that specifies the object for which it is to acquire a lock:</p><a id="I_9_tt501"/><pre class="programlisting"> <code class="kd">synchronized</code> <code class="o">(</code> <code class="n">myObject</code> <code class="o">)</code> <code class="o">{</code> <code class="c1">// Functionality that needs exclusive access to resources</code> <code class="o">}</code></pre><p>This code block can appear in any method. When it is reached, the thread has to acquire the lock on <code class="literal">myObject</code> before proceeding. In this way, we can synchronize methods (or parts of methods) in different classes in the same way as methods in the same class.</p><p>A synchronized instance method is, therefore, equivalent to a method with its statements synchronized on the current object. Thus:</p><a id="I_9_tt502"/><pre class="programlisting"> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">myMethod</code> <code class="o">()</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code></pre><p>is equivalent to:<a id="I_indexterm9_id716489" class="indexterm"/></p><a id="I_9_tt503"/><pre class="programlisting"> <code class="kt">void</code> <code class="nf">myMethod</code> <code class="o">()</code> <code class="o">{</code> <code class="kd">synchronized</code> <code class="o">(</code> <code class="k">this</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code> <code class="o">}</code></pre></div><div class="sect2" title="Accessing class and instance Variables from Multiple Threads"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-9-SECT-3.2"/>Accessing class and instance Variables from Multiple Threads</h2></div></div></div><p><a id="I_indexterm9_id716512" class="indexterm"/>In the <code class="literal">SpreadSheet</code> example, we guarded access to a set of instance variables with a synchronized method in order to avoid changing one of the variables while someone was reading the others. We wanted to keep them coordinated. But what about individual variable types? Do they need to be synchronized? Normally, the answer is no. Almost all operations on primitives and object reference types in Java happen <span class="emphasis"><em>atomically</em></span>: that is, they are handled by the VM in one step, with no opportunity for two threads to collide. This prevents threads from looking at references while they are in the process of being accessed by other threads.</p><p>But watch out—we did say <span class="emphasis"><em>almost</em></span>. If you read the Java VM specification carefully, you will see that the <a id="I_indexterm9_id716544" class="indexterm"/><code class="literal">double</code> and <a id="I_indexterm9_id716558" class="indexterm"/><code class="literal">long</code> primitive types are not guaranteed to be handled atomically. Both of these types represent 64-bit values. The problem has to do with how the Java VM’s stack handles them. It is possible that this specification will be beefed up in the future. But for now, to be strict, you should synchronize access to your <code class="literal">double</code> and <code class="literal">long</code> instance variables through accessor methods, or use the <a id="I_indexterm9_id716587" class="indexterm"/><code class="literal">volatile</code> keyword or an atomic wrapper class, which we’ll describe next.</p><p>Another issue, independent of the atomicity of the values, is the notion of different threads in the VM caching values for periods of time—that is, even though one thread may have changed the value, the Java VM may not be obliged to make that value appear until the VM reaches a certain state known as a “memory barrier.” While this should not be a problem in most real-world programming cases, you can address this by declaring the variable with the <code class="literal">volatile</code> keyword. This keyword indicates to the VM that the value may be changed by external threads and effectively synchronizes access to it automatically.</p><p>Finally, the <a id="I_indexterm9_id716618" class="indexterm"/><code class="literal">java.util.concurrent.atomic</code> package provides synchronized wrapper classes for all primitive types and references. These wrappers provide not only simple <code class="literal">set()</code> and <code class="literal">get()</code> operations on the values but also specialized “combo” operations, such as <a id="I_indexterm9_id716642" class="indexterm"/><code class="literal">compareAndSet()</code>, that work atomically and can be used to build higher-level synchronized application components. The classes in this package were designed specifically to map down to hardware-level functionality in many cases and can be very efficient. We’ll talk more about them later in this chapter.</p><div class="sect3" title="Reentrant locking"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-9-SECT-3.2.2"/>Reentrant locking</h3></div></div></div><p><a id="I_indexterm9_id716665" class="indexterm"/>The locks acquired by Java upon entering a synchronized method or block of code are <span class="emphasis"><em>reentrant</em></span>, meaning that the thread holding onto the lock may acquire the same lock again any number of times and never blocks waiting for itself. In most cases, this means that the code behaves as you’d expect; a thread can call a synchronized method recursively and can itself call upon other synchronized methods within the same object.</p></div></div><div class="sect2" title="The wait() and notify() Methods"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-9-SECT-3.3"/>The wait() and notify() Methods</h2></div></div></div><p><a id="idx10476" class="indexterm"/> <a id="idx10500" class="indexterm"/> <a id="idx10504" class="indexterm"/> <a id="idx10511" class="indexterm"/>With the <code class="literal">synchronized</code> keyword, we can serialize the execution of methods and blocks of code so that only one thread at a time can execute a synchronized item. The <code class="literal">wait()</code> and <code class="literal">notify()</code> methods of the <a id="I_indexterm9_id716757" class="indexterm"/><code class="literal">Object</code> class extend this capability by allowing us to explicitly coordinate the waiting and running threads. Every object in Java is a subclass of <code class="literal">Object</code>, so every object inherits these methods. By using <code class="literal">wait()</code> and <code class="literal">notify()</code>, a thread can effectively give up its hold on a lock at an arbitrary point and then wait for another thread to give it back before continuing. All of the coordinated activity still happens inside synchronized blocks, and still only one thread is executing at a given time.</p><p>By executing <code class="literal">wait()</code> from a synchronized block, a thread gives up its hold on the lock and goes to sleep. A thread might do this if it needs to wait for something to happen in another part of the application, as we’ll see shortly. Later, when the necessary event happens, the running thread calls <code class="literal">notify()</code> from a block synchronized on the same object. The first thread wakes up and begins trying to acquire the lock again. When the first thread manages to reacquire the lock, it continues from where it left off. However, the thread that was waiting may not get the lock immediately (or perhaps ever). It depends on when the second thread eventually releases the lock and which thread manages to snag it next. The first thread won’t wake up from the <code class="literal">wait()</code> unless another thread calls <code class="literal">notify()</code>. An overloaded version of <code class="literal">wait()</code>, however, allows us to specify a timeout period. If another thread doesn’t call <code class="literal">notify()</code> in the specified period, the waiting thread automatically wakes up.</p><p>Let’s look at a simple scenario to see what’s going on. In the following example, we’ll assume there are three threads—one waiting to execute each of the three synchronized methods of the <code class="literal">MyThing</code> class. We’ll call them the <span class="emphasis"><em>waiter</em></span>, <span class="emphasis"><em>notifier</em></span>, and <span class="emphasis"><em>related</em></span> threads. Here’s a code fragment to illustrate:</p><a id="I_9_tt504"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">MyThing</code> <code class="o">{</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">waiterMethod</code><code class="o">()</code> <code class="o">{</code> <code class="c1">// do some stuff</code> <code class="n">wait</code><code class="o">();</code> <code class="c1">// now wait for notifier to do something</code> <code class="c1">// continue where we left off</code> <code class="o">}</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">notifierMethod</code><code class="o">()</code> <code class="o">{</code> <code class="c1">// do some stuff</code> <code class="n">notify</code><code class="o">();</code> <code class="c1">// notify waiter that we've done it</code> <code class="c1">// continue doing stuff</code> <code class="o">}</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">relatedMethod</code><code class="o">()</code> <code class="o">{</code> <code class="c1">// do some related stuff</code> <code class="o">}</code> <code class="o">...</code> <code class="o">}</code></pre><p>Let’s assume that a thread named <span class="emphasis"><em>waiter</em></span> gets through the gate first and begins executing <code class="literal">waiterMethod()</code>. The two other threads are initially blocked when trying to acquire the lock for the <code class="literal">MyThing</code> object. When <span class="emphasis"><em>waiter</em></span> executes the <code class="literal">wait()</code> method, it relinquishes its hold on the lock and goes to sleep. Now two viable threads are waiting for the lock. Which thread gets it depends on several factors, including chance and the priorities of the threads. (We’ll discuss thread scheduling in the next section.)</p><p>Let’s suppose that <span class="emphasis"><em>notifier</em></span> is the next thread to acquire the lock, so it begins to run <code class="literal">notifierMethod()</code>. <span class="emphasis"><em>waiter</em></span> continues to sleep, and <span class="emphasis"><em>related</em></span> languishes, waiting for its turn. When <span class="emphasis"><em>notifier</em></span> executes the call to <code class="literal">notify()</code>, the runtime system prods the <span class="emphasis"><em>waiter</em></span> thread, effectively telling it something has changed. <span class="emphasis"><em>waiter</em></span> wakes up and rejoins <span class="emphasis"><em>related</em></span> in vying for the <code class="literal">MyThing</code> lock. It doesn’t receive the lock automatically; it just changes its state from “Leave me alone” to “I want the lock.”</p><p>At this point, <span class="emphasis"><em>notifier</em></span> still owns the lock and continues to hold it until the synchronized <code class="literal">notifierMethod()</code> returns, or perhaps executes a <code class="literal">wait()</code> itself. At that point, the other two methods get to fight over the lock. <span class="emphasis"><em>waiter</em></span> would like to continue executing <code class="literal">waiterMethod()</code> from the point where it left off, while <span class="emphasis"><em>related</em></span>, which has been patient, would like to get started. We’ll let you choose your own ending for the story.</p><p>For each call to <code class="literal">notify()</code>, the runtime system wakes up just one thread that is asleep in a <code class="literal">wait()</code> call. The group of threads waiting on a lock is called the <span class="emphasis"><em>wait set</em></span>. If multiple threads are waiting, Java picks a thread on an arbitrary basis, which may be implementation-dependent. The <a id="I_indexterm9_id717005" class="indexterm"/><code class="literal">Object</code> class also provides a <code class="literal">notifyAll()</code> call to wake up all waiting threads. In most cases, you’ll probably want to use <code class="literal">notifyAll()</code> rather than <code class="literal">notify()</code>. Keep in mind that <code class="literal">notify()</code> really means, “Hey, something related to this object has changed. The condition you are waiting for may have changed, so check it again.” In general, there is no reason to assume only one thread at a time is interested in the change or able to act upon it. Different threads might look upon whatever has changed in different ways.</p><div class="sect3" title="Wait conditions"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-9-SECT-3.3.1"/>Wait conditions</h3></div></div></div><p>In general, our <span class="emphasis"><em>waiter</em></span> thread is waiting for a particular condition to change, and we will want it to sit in a loop like the following:</p><a id="I_9_tt505"/><pre class="programlisting"> <code class="k">while</code> <code class="o">(</code> <code class="n">condition</code> <code class="o">!=</code> <code class="kc">true</code> <code class="o">)</code> <code class="n">wait</code><code class="o">();</code></pre><p>This test is called the <span class="emphasis"><em>wait condition</em></span>. Other synchronized threads call <code class="literal">notify()</code> or <a id="I_indexterm9_id717079" class="indexterm"/><code class="literal">notifyAll()</code> when they have modified the environment so that the condition can be checked again. It’s important to use a loop on the wait condition to be sure that the thread has been awakened for the right reason. Threads may also use a timed version of <code class="literal">wait()</code> to do periodic work while checking the condition in this way. Using wait conditions like this is also an alternative to polling and sleeping, as you’ll see in the following section.<a id="I_indexterm9_id717103" class="indexterm"/><a id="I_indexterm9_id717110" class="indexterm"/><a id="I_indexterm9_id717117" class="indexterm"/><a id="I_indexterm9_id717124" class="indexterm"/></p></div></div><div class="sect2" title="Passing Messages"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-9-SECT-3.4"/>Passing Messages</h2></div></div></div><p><a id="idx10501" class="indexterm"/>We’ll next illustrate a classic interaction between two threads: a <code class="literal">Producer</code> and a <code class="literal">Consumer</code>. A producer thread creates messages and places them into a queue while a consumer reads and displays them. To be realistic, we’ll give the queue a maximum depth. And to make things really interesting, we’ll have our consumer thread be lazy and run much more slowly than the producer. This means that <code class="literal">Producer</code> occasionally has to stop and wait for <code class="literal">Consumer</code> to catch up. The Java concurrency package has a <a id="I_indexterm9_id717182" class="indexterm"/><code class="literal">BlockingQueue</code> interface that provides exactly this kind of functionality, but we’ll build it ourselves here using basic synchronization techniques first and then take a look at <code class="literal">Queue</code>s and all of the collection classes in <a class="xref" href="ch11.html" title="Chapter 11. Core Utilities">Chapter 11</a>.</p><p>Here are the <code class="literal">Producer</code> and <code class="literal">Consumer</code> classes:</p><a id="I_9_tt506"/><pre class="programlisting"> <code class="kn">import</code> <code class="nn">java.util.*</code><code class="o">;</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">Consumer</code> <code class="kd">implements</code> <code class="n">Runnable</code> <code class="o">{</code> <code class="n">Producer</code> <code class="n">producer</code><code class="o">;</code> <code class="n">Consumer</code><code class="o">(</code> <code class="n">Producer</code> <code class="n">producer</code> <code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">producer</code> <code class="o">=</code> <code class="n">producer</code><code class="o">;</code> <code class="o">}</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">run</code><code class="o">()</code> <code class="o">{</code> <code class="k">while</code> <code class="o">(</code> <code class="kc">true</code> <code class="o">)</code> <code class="o">{</code> <code class="n">String</code> <code class="n">message</code> <code class="o">=</code> <code class="n">producer</code><code class="o">.</code><code class="na">getMessage</code><code class="o">();</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"Got message: "</code> <code class="o">+</code> <code class="n">message</code><code class="o">);</code> <code class="k">try</code> <code class="o">{</code> <code class="n">Thread</code><code class="o">.</code><code class="na">sleep</code><code class="o">(</code> <code class="mi">2000</code> <code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InterruptedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code> <code class="n">args</code><code class="o">[])</code> <code class="o">{</code> <code class="n">Producer</code> <code class="n">producer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Producer</code><code class="o">();</code> <code class="k">new</code> <code class="nf">Thread</code><code class="o">(</code> <code class="n">producer</code> <code class="o">).</code><code class="na">start</code><code class="o">();</code> <code class="n">Consumer</code> <code class="n">consumer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Consumer</code><code class="o">(</code> <code class="n">producer</code> <code class="o">);</code> <code class="k">new</code> <code class="nf">Thread</code><code class="o">(</code> <code class="n">consumer</code> <code class="o">).</code><code class="na">start</code><code class="o">();</code> <code class="o">}</code> <code class="o">}</code> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">Producer</code> <code class="kd">implements</code> <code class="n">Runnable</code><code class="o">{</code> <code class="kd">static</code> <code class="kd">final</code> <code class="kt">int</code> <code class="n">MAXQUEUE</code> <code class="o">=</code> <code class="mi">5</code><code class="o">;</code> <code class="kd">private</code> <code class="n">List</code> <code class="n">messages</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o">();</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">run</code><code class="o">()</code> <code class="o">{</code> <code class="k">while</code> <code class="o">(</code> <code class="kc">true</code> <code class="o">)</code> <code class="o">{</code> <code class="n">putMessage</code><code class="o">();</code> <code class="k">try</code> <code class="o">{</code> <code class="n">Thread</code><code class="o">.</code><code class="na">sleep</code><code class="o">(</code> <code class="mi">1000</code> <code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InterruptedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code> <code class="c1">// called by Producer internally</code> <code class="kd">private</code> <code class="kd">synchronized</code> <code class="kt">void</code> <code class="nf">putMessage</code><code class="o">()</code> <code class="o">{</code> <code class="k">while</code> <code class="o">(</code> <code class="n">messages</code><code class="o">.</code><code class="na">size</code><code class="o">()</code> <code class="o">&gt;=</code> <code class="n">MAXQUEUE</code> <code class="o">)</code> <code class="k">try</code> <code class="o">{</code> <code class="n">wait</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code><code class="o">(</code> <code class="n">InterruptedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code> <code class="n">messages</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="k">new</code> <code class="n">java</code><code class="o">.</code><code class="na">util</code><code class="o">.</code><code class="na">Date</code><code class="o">().</code><code class="na">toString</code><code class="o">()</code> <code class="o">);</code> <code class="n">notify</code><code class="o">();</code> <code class="o">}</code> <code class="c1">// called by Consumer externally</code> <code class="kd">public</code> <code class="kd">synchronized</code> <code class="n">String</code> <code class="nf">getMessage</code><code class="o">()</code> <code class="o">{</code> <code class="k">while</code> <code class="o">(</code> <code class="n">messages</code><code class="o">.</code><code class="na">size</code><code class="o">()</code> <code class="o">==</code> <code class="mi">0</code> <code class="o">)</code> <code class="k">try</code> <code class="o">{</code> <code class="n">notify</code><code class="o">();</code> <code class="n">wait</code><code class="o">();</code> <code class="o">}</code> <code class="k">catch</code><code class="o">(</code> <code class="n">InterruptedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code> <code class="n">String</code> <code class="n">message</code> <code class="o">=</code> <code class="o">(</code><code class="n">String</code><code class="o">)</code><code class="n">messages</code><code class="o">.</code><code class="na">remove</code><code class="o">(</code><code class="mi">0</code><code class="o">);</code> <code class="n">notify</code><code class="o">();</code> <code class="k">return</code> <code class="n">message</code><code class="o">;</code> <code class="o">}</code> <code class="o">}</code></pre><p>For convenience, we have included a <code class="literal">main()</code> method in the <code class="literal">Consumer</code> class that runs the complete example. It creates a <code class="literal">Consumer</code> that is tied to a <code class="literal">Producer</code> and starts the two classes. You can run the example as follows:</p><a id="I_9_tt507"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="n">Consumer</code></code></strong></pre><p>This produces the timestamp messages created by the <code class="literal">Producer</code>:</p><a id="I_9_tt508"/><pre class="programlisting"> <code class="n">Got</code> <code class="nl">message:</code> <code class="n">Sun</code> <code class="n">Dec</code> <code class="mi">19</code> <code class="mi">03</code><code class="o">:</code><code class="mi">35</code><code class="o">:</code><code class="mi">55</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Got</code> <code class="nl">message:</code> <code class="n">Sun</code> <code class="n">Dec</code> <code class="mi">19</code> <code class="mi">03</code><code class="o">:</code><code class="mi">35</code><code class="o">:</code><code class="mi">56</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Got</code> <code class="nl">message:</code> <code class="n">Sun</code> <code class="n">Dec</code> <code class="mi">19</code> <code class="mi">03</code><code class="o">:</code><code class="mi">35</code><code class="o">:</code><code class="mi">57</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="o">...</code></pre><p>The timestamps initially show a spacing of one second even though they appear every two seconds. Our <code class="literal">Producer</code> runs faster than our <code class="literal">Consumer</code>. <code class="literal">Producer</code> would like to generate a new message every second, while <code class="literal">Consumer</code> gets around to reading and displaying a message only every two seconds. Can you see how long it will take the message queue to fill up? What happens when it does?</p><p>Let’s look at the code. We are using a few new tools here. <code class="literal">Producer</code> and <code class="literal">Consumer</code> implement the <code class="literal">Runnable</code> interface, and each has a thread associated with it. The <code class="literal">Producer</code> and <code class="literal">Consumer</code> classes pass messages through an instance of a <code class="literal">java.util.List</code> object. We haven’t discussed the <code class="literal">List</code> class yet, but it is essentially a dynamic array of elements. We use this one as a queue by simply adding and removing elements in first-in, first-out order. The <code class="literal">List</code> has no maximum capacity of its own, but we impose one with our own check.</p><p>The important activity is in the synchronized methods: <code class="literal">putMessage()</code> and <code class="literal">getMessage()</code>. Although one of the methods is used by the <code class="literal">Producer</code> thread and the other by the <code class="literal">Consumer</code> thread, they both live in the <code class="literal">Producer</code> class so that we can coordinate them simply by declaring them <a id="I_indexterm9_id717410" class="indexterm"/><code class="literal">synchronized</code>. Here, they both implicitly use the <code class="literal">Producer</code> object’s lock. If the queue is empty, the <code class="literal">Consumer</code> blocks in a call in the <code class="literal">Producer</code>, waiting for another message.</p><p>Another design option would implement the <code class="literal">getMessage()</code> method in the <code class="literal">Consumer</code> class and use a <code class="literal">synchronized</code> code block to synchronize explicitly on the <code class="literal">Producer</code> object. In either case, synchronizing on the <code class="literal">Producer</code> enables us to have multiple <code class="literal">Consumer</code> objects that feed from the same <code class="literal">Producer</code>. We’ll do that later in this section.</p><p><code class="literal">putMessage()</code>’s job is to add a new message to the queue. It can’t do this if the queue is already full, so it first checks the number of elements in <code class="literal">messages</code>. If there is room, it stuffs in another timestamp message. If the queue is at its limit, however, <code class="literal">putMessage()</code> has to wait until there’s space. In this situation, <code class="literal">putMessage()</code> executes a <code class="literal">wait()</code> and relies on the consumer to call <code class="literal">notify()</code> to wake it up after a message has been read. Here, we have <code class="literal">putMessage()</code> testing the condition in a loop. In this simple example, the test might not seem necessary; we could assume that when <code class="literal">putMessage()</code> wakes up, there is a free spot. However, it’s important to always test our wait condition in a loop like this when we synchronize threads because there is no other way to be certain why our thread has been awakened. Before it finishes, <code class="literal">putMessage()</code> calls <code class="literal">notify()</code> itself to prod any <code class="literal">Consumer</code> that might be waiting on an empty queue.</p><p><code class="literal">getMessage()</code> retrieves a message for the <code class="literal">Consumer</code>. It enters a loop like that of <code class="literal">putMessage()</code>, waiting for the queue to have at least one element before proceeding. If the queue is empty, it executes a <a id="I_indexterm9_id717569" class="indexterm"/><code class="literal">wait()</code> and expects the <code class="literal">Producer</code> to call <a id="I_indexterm9_id717585" class="indexterm"/><code class="literal">notify()</code> when more items are available. Notice that <code class="literal">getMessage()</code> makes its own calls to <code class="literal">notify()</code>. It does this any time the queue is empty, to prod a producer that might be sleeping and also after it consumes a message, to give the producer the go-ahead to fill the queue again. These scenarios are more plausible if there are more consumers, as we’ll see next.</p><p>Let’s add another consumer to the scenario, just to make things more interesting. Most of the necessary changes are in the <code class="literal">Consumer</code> class; here’s the code for the modified class, now called <code class="literal">NamedConsumer</code>:</p><a id="I_9_tt509"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">NamedConsumer</code> <code class="kd">implements</code> <code class="n">Runnable</code> <code class="o">{</code> <code class="n">Producer</code> <code class="n">producer</code><code class="o">;</code> <code class="n">String</code> <code class="n">name</code><code class="o">;</code> <code class="n">NamedConsumer</code><code class="o">(</code><code class="n">String</code> <code class="n">name</code><code class="o">,</code> <code class="n">Producer</code> <code class="n">producer</code><code class="o">)</code> <code class="o">{</code> <code class="k">this</code><code class="o">.</code><code class="na">producer</code> <code class="o">=</code> <code class="n">producer</code><code class="o">;</code> <code class="k">this</code><code class="o">.</code><code class="na">name</code> <code class="o">=</code> <code class="n">name</code><code class="o">;</code> <code class="o">}</code> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">run</code><code class="o">()</code> <code class="o">{</code> <code class="k">while</code> <code class="o">(</code> <code class="kc">true</code> <code class="o">)</code> <code class="o">{</code> <code class="n">String</code> <code class="n">message</code> <code class="o">=</code> <code class="n">producer</code><code class="o">.</code><code class="na">getMessage</code><code class="o">();</code> <code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="n">name</code> <code class="o">+</code> <code class="s">" got message: "</code> <code class="o">+</code> <code class="n">message</code><code class="o">);</code> <code class="k">try</code> <code class="o">{</code> <code class="n">Thread</code><code class="o">.</code><code class="na">sleep</code><code class="o">(</code> <code class="mi">2000</code> <code class="o">);</code> <code class="o">}</code> <code class="k">catch</code> <code class="o">(</code> <code class="n">InterruptedException</code> <code class="n">e</code> <code class="o">)</code> <code class="o">{</code> <code class="o">}</code> <code class="o">}</code> <code class="o">}</code> <code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code> <code class="n">args</code><code class="o">[])</code> <code class="o">{</code> <code class="n">Producer</code> <code class="n">producer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Producer</code><code class="o">();</code> <code class="k">new</code> <code class="nf">Thread</code><code class="o">(</code> <code class="n">producer</code> <code class="o">).</code><code class="na">start</code><code class="o">();</code> <code class="n">NamedConsumer</code> <code class="n">consumer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">NamedConsumer</code><code class="o">(</code> <code class="s">"One"</code><code class="o">,</code> <code class="n">producer</code> <code class="o">);</code> <code class="k">new</code> <code class="nf">Thread</code><code class="o">(</code> <code class="n">consumer</code> <code class="o">).</code><code class="na">start</code><code class="o">();</code> <code class="n">consumer</code> <code class="o">=</code> <code class="k">new</code> <code class="n">NamedConsumer</code><code class="o">(</code> <code class="s">"Two"</code><code class="o">,</code> <code class="n">producer</code> <code class="o">);</code> <code class="k">new</code> <code class="nf">Thread</code><code class="o">(</code> <code class="n">consumer</code> <code class="o">).</code><code class="na">start</code><code class="o">();</code> <code class="o">}</code> <code class="o">}</code></pre><p>The <code class="literal">NamedConsumer</code> constructor takes a string name to identify each consumer. The <a id="I_indexterm9_id717651" class="indexterm"/><code class="literal">run()</code> method uses this name in the call to <code class="literal">println()</code> to identify which consumer received the message.</p><p>The only required modification to the <code class="literal">Producer</code> code is to change the <code class="literal">notify()</code> calls to <code class="literal">notifyAll()</code> calls in <code class="literal">putMessage()</code> and <code class="literal">getMessage()</code>. (We could have used <code class="literal">notifyAll()</code> in the first place.) Now, instead of the consumer and producer playing tag with the queue, we can have many players waiting for the condition of the queue to change. We might have a number of consumers waiting for a message, or we might have the producer waiting for a consumer to take a message. Any time the condition of the queue changes, we prod all of the waiting methods to reevaluate the situation by calling <code class="literal">notifyAll()</code>.</p><p>Here is some sample output when two <code class="literal">NamedConsumers</code> are running, as in the <code class="literal">main()</code> method shown previously:</p><a id="I_9_tt510"/><pre class="programlisting"> <code class="n">One</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">01</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Two</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">02</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">One</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">03</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Two</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">04</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">One</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">05</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Two</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">06</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">One</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">07</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="n">Two</code> <code class="n">got</code> <code class="nl">message:</code> <code class="n">Sat</code> <code class="n">Mar</code> <code class="mi">18</code> <code class="mi">20</code><code class="o">:</code><code class="mi">00</code><code class="o">:</code><code class="mi">08</code> <code class="n">CST</code> <code class="mi">2006</code> <code class="o">...</code></pre><p>We see nice, orderly alternation between the two consumers as a result of the calls to <a id="I_indexterm9_id717740" class="indexterm"/><code class="literal">sleep()</code> in the various methods. Interesting things would happen, however, if we were to remove all calls to <code class="literal">sleep()</code> and let things run at full speed. The threads would compete, and their behavior would depend on whether the system is using time-slicing. On a time-sliced