UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

103 lines (99 loc) 12.5 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>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>