⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tij0156.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<html><body>

<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0155.html">Prev</a> | <a href="tij0157.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
Sharing
limited resources
<P><A NAME="Index2489"></A></H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can think of a single-threaded program as one lonely entity moving around
through your problem space and doing one thing at a time. Because there&#8217;s
only one entity, you never have to think about the problem of two entities
trying to use the same resource at the same time, like two people trying to
park in the same space, walk through a door at the same time, or even talk at
the same time.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">With
multithreading, things aren&#8217;t lonely anymore, but you now have the
possibility of two or more threads trying to use the same limited resource at
once. Colliding over a resource must be prevented or else you&#8217;ll have two
threads trying to access the same bank account at the same time, print to the
same printer, or adjust the same valve, etc.
</FONT><a name="_Toc375545479"></a><a name="_Toc408018752"></a><P></DIV>
<A NAME="Heading490"></A><H3 ALIGN=LEFT>
Improperly
accessing resources
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Consider
a variation on the counters that have been used so far in this chapter. In the
following example, each thread contains two counters that are incremented and
displayed inside 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In addition, there&#8217;s another thread of class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that is watching the counters to see if they&#8217;re always equivalent. This
seems like a needless activity, since looking at the code it appears obvious
that the counters will always be the same. But that&#8217;s where the surprise
comes in. Here&#8217;s the first version of the program:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: Sharing1.java</font>
<font color="#009900">// Problems with resource sharing while threading</font>
<font color="#0000ff">import</font> java.awt.*;
<font color="#0000ff">import</font> java.awt.event.*;
<font color="#0000ff">import</font> java.applet.*;

<font color="#0000ff">class</font> TwoCounter <font color="#0000ff">extends</font> Thread {
  <font color="#0000ff">private</font> <font color="#0000ff">boolean</font> started = <font color="#0000ff">false</font>;
  <font color="#0000ff">private</font> TextField 
    t1 = <font color="#0000ff">new</font> TextField(5),
    t2 = <font color="#0000ff">new</font> TextField(5);
  <font color="#0000ff">private</font> Label l = 
    <font color="#0000ff">new</font> Label("count1 == count2");
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> count1 = 0, count2 = 0;
  <font color="#009900">// Add the display components as a panel</font>
  <font color="#009900">// to the given container:</font>
  <font color="#0000ff">public</font> TwoCounter(Container c) {
    Panel p = <font color="#0000ff">new</font> Panel();
    p.add(t1);
    p.add(t2);
    p.add(l);
    c.add(p);
  }
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> start() {
    <font color="#0000ff">if</font>(!started) {
      started = <font color="#0000ff">true</font>;
      <font color="#0000ff">super</font>.start();
    }
  }
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
    <font color="#0000ff">while</font> (<font color="#0000ff">true</font>) {
      t1.setText(Integer.toString(count1++));
      t2.setText(Integer.toString(count2++));
      <font color="#0000ff">try</font> {
        sleep(500);
      } <font color="#0000ff">catch</font> (InterruptedException e){}
    }
  }
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> synchTest() {
    Sharing1.incrementAccess();
    <font color="#0000ff">if</font>(count1 != count2)
      l.setText("Unsynched");
  }
}

<font color="#0000ff">class</font> Watcher <font color="#0000ff">extends</font> Thread {
  <font color="#0000ff">private</font> Sharing1 p;
  <font color="#0000ff">public</font> Watcher(Sharing1 p) { 
    <font color="#0000ff">this</font>.p = p;
    start();
  }
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
    <font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
      <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; p.s.length; i++)
        p.s[i].synchTest();
      <font color="#0000ff">try</font> {
        sleep(500);
      } <font color="#0000ff">catch</font> (InterruptedException e){}
    }
  }
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> Sharing1 <font color="#0000ff">extends</font> Applet {
  TwoCounter[] s;
  <font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">int</font> accessCount = 0;
  <font color="#0000ff">private</font> <font color="#0000ff">static</font> TextField aCount = 
    <font color="#0000ff">new</font> TextField("0", 10);
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> incrementAccess() {
    accessCount++;
    aCount.setText(Integer.toString(accessCount));
  }
  <font color="#0000ff">private</font> Button 
    start = <font color="#0000ff">new</font> Button("Start"),
    observer = <font color="#0000ff">new</font> Button("Observe");
  <font color="#0000ff">private</font> <font color="#0000ff">boolean</font> isApplet = <font color="#0000ff">true</font>;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> numCounters = 0;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> numObservers = 0;
  <font color="#0000ff">public</font> <font color="#0000ff">void</font> init() {
    <font color="#0000ff">if</font>(isApplet) {
      numCounters = 
        Integer.parseInt(getParameter("size"));
      numObservers = 
        Integer.parseInt(
          getParameter("observers"));
    }
    s = <font color="#0000ff">new</font> TwoCounter[numCounters];
    <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; s.length; i++)
      s[i] = <font color="#0000ff">new</font> TwoCounter(<font color="#0000ff">this</font>);
    Panel p = <font color="#0000ff">new</font> Panel();
    start.addActionListener(<font color="#0000ff">new</font> StartL());
    p.add(start);
    observer.addActionListener(<font color="#0000ff">new</font> ObserverL());
    p.add(observer);
    p.add(<font color="#0000ff">new</font> Label("Access Count"));
    p.add(aCount);
    add(p);
  }
  <font color="#0000ff">class</font> StartL <font color="#0000ff">implements</font> ActionListener {
    <font color="#0000ff">public</font> <font color="#0000ff">void</font> actionPerformed(ActionEvent e) {
      <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; s.length; i++)
        s[i].start();
    }
  }
  <font color="#0000ff">class</font> ObserverL <font color="#0000ff">implements</font> ActionListener {
    <font color="#0000ff">public</font> <font color="#0000ff">void</font> actionPerformed(ActionEvent e) {
      <font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i &lt; numObservers; i++)
        <font color="#0000ff">new</font> Watcher(Sharing1.<font color="#0000ff">this</font>);
    }
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Sharing1 applet = <font color="#0000ff">new</font> Sharing1();
    <font color="#009900">// This isn't an applet, so set the flag and</font>
    <font color="#009900">// produce the parameter values from args:</font>
    applet.isApplet = <font color="#0000ff">false</font>;
    applet.numCounters = 
      (args.length == 0 ? 5 :
        Integer.parseInt(args[0]));
    applet.numObservers =
      (args.length &lt; 2 ? 5 :
        Integer.parseInt(args[1]));
    Frame aFrame = <font color="#0000ff">new</font> Frame("Sharing1");
    aFrame.addWindowListener(
      <font color="#0000ff">new</font> WindowAdapter() {
        <font color="#0000ff">public</font> <font color="#0000ff">void</font> windowClosing(WindowEvent e){
          System.exit(0);
        }
      });
    aFrame.add(applet, BorderLayout.CENTER);
    aFrame.setSize(350, applet.numCounters *100);
    applet.init();
    applet.start();
    aFrame.setVisible(<font color="#0000ff">true</font>);
  }
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
before, each counter contains its own display components: two text fields and a
label that initially indicates that the counts are equivalent. These components
are added to the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Container
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">in
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TwoCounter</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
constructor. Because this thread is started via a button press by the user,
it&#8217;s possible that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>start(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
could be called more than once. It&#8217;s illegal for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread.start(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to be called more than once for a thread (an exception is thrown). You can see
that the machinery to prevent this in the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>started
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">flag
and the overridden 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>start(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>count1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>count2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are incremented and displayed in a manner that would seem to keep them
identical. Then <A NAME="Index2490"></A><A NAME="Index2491"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is called; without this call the program balks because it becomes hard for the
CPU to swap tasks.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchTest(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method performs the apparently useless activity of checking to see if 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>count1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is equivalent to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>count2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">;
if they are not equivalent it sets the label to &#8220;Unsynched&#8221; to
indicate this. But first, it calls a static member of the class 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sharing1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that increments and displays an access counter to show how many times this
check has occurred successfully. (The reason for this will become apparent in
future variations of this example.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class is a thread whose job is to call 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchTest(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for all of the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TwoCounter</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects that are active. It does this by stepping through the array
that&#8217;s kept in the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sharing1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object. You can think of the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as constantly peeking over the shoulders of the 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -