epubjs
Version:
Render ePub documents in the browser, across many devices
103 lines (99 loc) • 12.5 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Threading an Applet</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="Threading an Applet"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-9-SECT-2"/>Threading an Applet</h1></div></div></div><p><a id="idx10443" class="indexterm"/> <a id="idx10510" class="indexterm"/>Applets are embeddable Java applications that are expected
to start and stop themselves on command, possibly many times in their
lifetime. A Java-enabled web browser normally starts an applet when the applet is
displayed and stops it when the user moves to another page or (in theory)
when the user scrolls the applet out of view. To conform to this API, we
would like an applet to cease its nonessential activity when it is stopped
and resume it when started again. We’ll talk about applets in <a class="xref" href="ch23.html" title="Chapter 23. Applets">Chapter 23</a>, but it’s not really essential to know
about them here. We’ll just use this as a more realistic example and as a
transition to talk about our next topic, synchronization.</p><p>In this section, we will build <code class="literal">UpdateApplet</code>, a simple base class for an applet
that maintains a thread to automatically update its display at regular
intervals. <code class="literal">UpdateApplet</code> handles the
basic creation and termination of the thread in the Applet’s <code class="literal">start()</code> and <code class="literal">stop()</code> methods:</p><a id="I_9_tt495"/><pre class="programlisting"> <code class="kd">public</code> <code class="kd">class</code> <code class="nc">UpdateApplet</code> <code class="kd">extends</code> <code class="n">java</code><code class="o">.</code><code class="na">applet</code><code class="o">.</code><code class="na">Applet</code>
<code class="kd">implements</code> <code class="n">Runnable</code>
<code class="o">{</code>
<code class="n">Thread</code> <code class="n">thread</code><code class="o">;</code>
<code class="kt">boolean</code> <code class="n">running</code><code class="o">;</code>
<code class="kt">int</code> <code class="n">updateInterval</code> <code class="o">=</code> <code class="mi">1000</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="n">running</code> <code class="o">)</code>
<code class="o">{</code>
<code class="n">repaint</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="n">updateInterval</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="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">"interrupted..."</code><code class="o">);</code>
<code class="k">return</code><code class="o">;</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">start</code><code class="o">()</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">"starting..."</code><code class="o">);</code>
<code class="k">if</code> <code class="o">(</code> <code class="o">!</code><code class="n">running</code> <code class="o">)</code> <code class="c1">// naive approach</code>
<code class="o">{</code>
<code class="n">running</code> <code class="o">=</code> <code class="kc">true</code><code class="o">;</code>
<code class="n">thread</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Thread</code><code class="o">(</code><code class="k">this</code><code class="o">);</code>
<code class="n">thread</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="kt">void</code> <code class="nf">stop</code><code class="o">()</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">"stopping..."</code><code class="o">);</code>
<code class="n">thread</code><code class="o">.</code><code class="na">interrupt</code><code class="o">();</code>
<code class="n">running</code> <code class="o">=</code> <code class="kc">false</code><code class="o">;</code>
<code class="o">}</code>
<code class="o">}</code></pre><p><code class="literal">UpdateApplet</code> is a <a id="I_indexterm9_id715848" class="indexterm"/><code class="literal">Runnable</code> object that
alternately sleeps and calls its <code class="literal">repaint()</code> method. (There’s nothing to paint,
though, so running this applet is kind of boring. Later we’ll subclass it
to implement a digital clock.) It has two other public methods: <code class="literal">start()</code> and <code class="literal">stop()</code>. These are methods of the <a id="I_indexterm9_id715878" class="indexterm"/><code class="literal">Applet</code> class we are
overriding; don’t confuse them with the similarly named methods of the
<code class="literal">Thread</code> class. These <code class="literal">start()</code> and <code class="literal">stop()</code> methods are called by the web browser or
applet viewer to tell the applet when it should and should not be
running.</p><p><code class="literal">UpdateApplet</code> illustrates an
environmentally friendly way to deal with threads in a simple applet.
<code class="literal">UpdateApplet</code> simply dismisses its
thread each time the applet is stopped and recreates it if the applet is
restarted. When <code class="literal">UpdateApplet</code>’s <code class="literal">start()</code> method is called, we first check to make
sure there is no currently running thread by checking the <code class="literal">running</code> flag. We then create one to begin our
execution. When our applet is subsequently asked to stop, we set the flag
indicating that it should stop and make sure the thread is awake by
invoking its <code class="literal">interrupt()</code> method. In
this way, we are sure to catch the thread either at the beginning of its
next iteration or when it goes to sleep.</p><p>With <code class="literal">UpdateApplet</code> doing all the
work for us, we can create the world’s simplest clock applet with just a
few lines of code. <a class="xref" href="ch09s02.html#learnjava3-CHP-9-FIG-3" title="Figure 9-3. The Clock applet">Figure 9-3</a> shows our
<code class="literal">Clock</code>.</p><div class="figure"><a id="learnjava3-CHP-9-FIG-3"/><div class="figure-contents"><div class="mediaobject"><a id="I_9_tt496"/><img src="httpatomoreillycomsourceoreillyimages1707631.png" alt="The Clock applet"/></div></div><p class="title">Figure 9-3. The Clock applet</p></div><p>Here’s the code:</p><a id="I_9_tt497"/><pre class="programlisting"> <code class="c1">//file: Clock.java</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">Clock</code> <code class="kd">extends</code> <code class="n">UpdateApplet</code> <code class="o">{</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">paint</code><code class="o">(</code> <code class="n">java</code><code class="o">.</code><code class="na">awt</code><code class="o">.</code><code class="na">Graphics</code> <code class="n">g</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">g</code><code class="o">.</code><code class="na">drawString</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="mi">10</code><code class="o">,</code> <code class="mi">25</code> <code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>The <code class="literal">java.util.Date().toString()</code>
method creates a string that contains the current time.</p><div class="sect2" title="Issues Lurking"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-9-SECT-2.1"/>Issues Lurking</h2></div></div></div><p>Our applet seems pretty straightforward and, in fact, works as
advertised. But some things in it should concern us when we’re thinking
about threads. Let’s look at that quick check of the <a id="I_indexterm9_id716016" class="indexterm"/><code class="literal">running</code> flag before we
start our new thread:</p><a id="I_9_tt498"/><pre class="programlisting"> <code class="k">if</code> <code class="o">(</code> <code class="o">!</code><code class="n">running</code> <code class="o">)</code> <code class="c1">// naive approach</code>
<code class="o">{</code>
<code class="n">running</code> <code class="o">=</code> <code class="kc">true</code><code class="o">;</code>
<code class="o">...</code> <code class="cm">/* start thread */</code></pre><p>Now, an <code class="literal">Applet</code>’s <code class="literal">start()</code> and <code class="literal">stop()</code> methods are guaranteed to be called in
sequence and probably by the same controlling thread. As a result, this
check for the existence of the running thread in <a id="I_indexterm9_id716056" class="indexterm"/><code class="literal">start()</code> may not seem
necessary here. The <a id="I_indexterm9_id716067" class="indexterm"/><code class="literal">stop()</code> method should
always be called before the <code class="literal">start()</code>
method is invoked again. But, in the style of defensive programming the
test seems like a good thing to do, right? That may be so, but, in
general, it’s not enough to prevent bad things from happening. The test
may prevent a simple case of misaligned <code class="literal">stop()</code> and <code class="literal">start()</code> calls, but the bigger question lurking
here is, What happens if <code class="literal">start()</code> and
<code class="literal">stop()</code> were called repeatedly or in
very quick succession in a multithreaded environment? In the extreme
case, it would be possible for two threads to enter the test at about
the same time and there is the chance that we could end up with multiple
threads started and out of our control. What is needed is a real way to
gain exclusive access to a resource (our flag) for a period of time.
That’s what synchronization is all about, and we’ll cover it in detail
in the next section and throughout the rest of this chapter.</p><p>With synchronization, we might also consider more complex
scenarios for our applet, such as keeping our thread alive but dormant
while the applet is stopped. This would allow us to preserve expensive
setup like network connections and clean them up later if
necessary.<a id="I_indexterm9_id716123" class="indexterm"/><a id="I_indexterm9_id716130" class="indexterm"/></p></div></div></body></html>