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

📄 tij0156.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 4 页
字号:
    <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> Watcher2(Sharing2.<font color="#0000ff">this</font>);
    }
  }
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
    Sharing2 applet = <font color="#0000ff">new</font> Sharing2();
    <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("Sharing2");
    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">You&#8217;ll
notice that 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>both</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchTest(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If you synchronize only one of the methods, then the other is free to ignore
the object lock and can be called with impunity. This is an important point:
Every method that accesses a critical shared resource must be 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
or it won&#8217;t work right.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Now
a new issue arises. The 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can never get a peek at what&#8217;s going on because the entire 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method has been 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and since 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is always running for each object the lock is always tied up and 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchTest(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can never be called. You can see this because the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>accessCount</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
never changes.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What
we&#8217;d like for this example is a way to isolate only 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>part</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of the code 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">.
The section of code you want to isolate this way is called a <A NAME="Index2502"></A><A NAME="Index2503"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>critical
section
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and you use the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword in a different way to set up a critical section. Java supports critical
sections with the <A NAME="Index2504"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>synchronized
block;
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
this time 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">is
used to specify the object whose lock is being used to synchronize the enclosed
code:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#0000ff">synchronized</font>(syncObject) {
  <font color="#009900">// This code can be accessed by only</font>
  <font color="#009900">// one thread at a time, assuming all</font>
  <font color="#009900">// threads respect syncObject's lock</font>
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Before
the synchronized block can be entered, the lock must be acquired on 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>syncObject</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If some other thread already has this lock, then the block cannot be entered
until the lock is given up.
</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>Sharing2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
example can be modified by removing the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword from the entire 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method and instead putting a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
block around the two critical lines. But what object should be used as the
lock? The one that is already respected by 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchTest(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is the current object (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)!
So the modified 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
looks like this:
</FONT><P></DIV>

<font color="#990000"><PRE>  <font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
    <font color="#0000ff">while</font> (<font color="#0000ff">true</font>) {
      <font color="#0000ff">synchronized</font>(<font color="#0000ff">this</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){}
    }
  } </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is the only change that must be made to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sharing2.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and you&#8217;ll see that while the two counters are never out of synch
(according to when the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is allowed to look at them), there is still adequate access provided to the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Watcher</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
during the execution of 
</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><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Of
course, all synchronization depends on programmer diligence: every piece of
code that can access a shared resource must be wrapped in an appropriate
synchronized block. 
</FONT><P></DIV>
<A NAME="Heading493"></A><H4 ALIGN=LEFT>
Synchronized
efficiency
<P><A NAME="Index2505"></A><A NAME="Index2506"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
having two methods write to the same piece of data 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>never
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">sounds
like a particularly good idea, it might seem to make sense for all methods to
be automatically 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and eliminate the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword altogether. (Of course, the example with a 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized
run(&#160;)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
shows that this wouldn&#8217;t work either.) But it turns out that acquiring a
lock is not a cheap operation &#8211; it multiplies the cost of a method call
(that is, entering and exiting from the method, not executing the body of the
method) by a minimum of four times, and could be more depending on your
implementation. So if you know that a particular method will not cause
contention problems it is expedient to leave off the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword.
</FONT><a name="_Toc408018754"></a><P></DIV>
<A NAME="Heading494"></A><H3 ALIGN=LEFT>
Java
Beans revisited
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Now
that you understand synchronization you can take another look at <A NAME="Index2507"></A><A NAME="Index2508"></A><A NAME="Index2509"></A>Java
Beans. Whenever you create a Bean, you must assume that it will run in a
multithreaded environment. This means that:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	Whenever
possible, all the public methods of a Bean should be 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Of course, this incurs the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
runtime overhead. If that&#8217;s a problem, methods that will not cause
problems in critical sections can be left un-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but keep in mind that this is not always obvious. Methods that qualify tend to
be small (such as 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getCircleSize(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in the following example) and/or &#8220;atomic,&#8221; that is, the method call
executes in such a short amount of code that the object cannot be changed
during execution. Making such methods un-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">might
not have a significant effect on the execution speed of your program. You might
as well make all 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods of a Bean 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and remove the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword only when you know for sure that it&#8217;s necessary and that it makes
a difference.
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">	When
firing a <A NAME="Index2510"></A><A NAME="Index2511"></A>multicast
event to a bunch of listeners interested in that event, you must assume that
listeners might be added or removed while moving through the list.
</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
first point is fairly easy to deal with, but the second point requires a little
more thought. Consider the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BangBean.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
example presented in the last chapter. That ducked out of the multithreading
question by ignoring the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword (which hadn&#8217;t been introduced yet) and making the event unicast.
Here&#8217;s that example modified to work in a multithreaded environment and
to use multicasting for events:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">//: BangBean2.java</font>
<font color="#009900">// You should write your Beans this way so they </font>
<font color="#009900">// can run in a multithreaded environment.</font>
<font color="#0000ff">import</font> java.awt.*;
<font color="#0000ff">import</font> java.awt.event.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">import</font> java.io.*;

<font color="#0000ff">public</font> <font color="#0000ff">class</font> BangBean2 <font color="#0000ff">extends</font> Canvas 
    <font color="#0000ff">implements</font> Serializable {
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> xm, ym;
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> cSize = 20; <font color="#009900">// Circle size</font>
  <font color="#0000ff">private</font> String text = "Bang!";
  <font color="#0000ff">private</font> <font color="#0000ff">int</font> fontSize = 48;
  <font color="#0000ff">private</font> Color tColor = Color.red;
  <font color="#0000ff">private</font> Vector actionListeners = <font color="#0000ff">new</font> Vector();
  <font color="#0000ff">public</font> BangBean2() {
    addMouseListener(<font color="#0000ff">new</font> ML());
    addMouseMotionListener(<font color="#0000ff">new</font> MM());
  }
  <font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">int</font> getCircleSize() { 
    <font color="#0000ff">return</font> cSize; 

⌨️ 快捷键说明

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