📄 tij0157.html
字号:
This is important: Note that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>read( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>update( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are both
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which means they require that the object lock be free.
</FONT><P></DIV>
<A NAME="Heading497"></A><H4 ALIGN=LEFT>
Sleeping</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
first test in this program is with <A NAME="Index2549"></A><A NAME="Index2550"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep( ):</B></FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">///:Continuing</font>
<font color="#009900">///////////// Blocking via sleep() ///////////</font>
<font color="#0000ff">class</font> Sleeper1 <font color="#0000ff">extends</font> Blockable {
<font color="#0000ff">public</font> Sleeper1(Container c) { <font color="#0000ff">super</font>(c); }
<font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
i++;
update();
<font color="#0000ff">try</font> {
sleep(1000);
} <font color="#0000ff">catch</font> (InterruptedException e){}
}
}
}
<font color="#0000ff">class</font> Sleeper2 <font color="#0000ff">extends</font> Blockable {
<font color="#0000ff">public</font> Sleeper2(Container c) { <font color="#0000ff">super</font>(c); }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
change();
<font color="#0000ff">try</font> {
sleep(1000);
} <font color="#0000ff">catch</font> (InterruptedException e){}
}
}
<font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">void</font> change() {
i++;
update();
}
} <font color="#009900">///:Continued </PRE></font></font><DIV ALIGN=LEFT><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>Sleeper1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the entire
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You’ll see that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
associated with this object will run along merrily
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>until</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you start the thread, and then the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
stops cold. This is one form of blocking: since
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sleeper1.run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and once the thread starts it’s always inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the method never gives up the object lock and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is blocked.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sleeper2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
provides a solution by making run un-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Only the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>change( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which means that while
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can access the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method it needs, namely
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>read( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Here you’ll see that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
continues running when you start the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Sleeper2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
thread.
</FONT><P></DIV>
<A NAME="Heading498"></A><H4 ALIGN=LEFT>
Suspending
and resuming
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next part of the example introduces the concept of suspension. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class has a method <A NAME="Index2551"></A><A NAME="Index2552"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to temporarily halt the thread and <A NAME="Index2553"></A><A NAME="Index2554"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>resume( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that re-starts it at the point it was halted. Presumably,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>resume( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is called by some thread outside the suspended one, and in this case
there’s a separate class called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Resumer</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that does just that. Each of the classes demonstrating suspend/resume has an
associated resumer:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">///:Continuing</font>
<font color="#009900">/////////// Blocking via suspend() ///////////</font>
<font color="#0000ff">class</font> SuspendResume <font color="#0000ff">extends</font> Blockable {
<font color="#0000ff">public</font> SuspendResume(Container c) {
<font color="#0000ff">super</font>(c);
<font color="#0000ff">new</font> Resumer(<font color="#0000ff">this</font>);
}
}
<font color="#0000ff">class</font> SuspendResume1 <font color="#0000ff">extends</font> SuspendResume {
<font color="#0000ff">public</font> SuspendResume1(Container c) { <font color="#0000ff">super</font>(c);}
<font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
i++;
update();
suspend(); <font color="#009900">// Deprecated in Java 1.2</font>
}
}
}
<font color="#0000ff">class</font> SuspendResume2 <font color="#0000ff">extends</font> SuspendResume {
<font color="#0000ff">public</font> SuspendResume2(Container c) { <font color="#0000ff">super</font>(c);}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">while</font>(<font color="#0000ff">true</font>) {
change();
suspend(); <font color="#009900">// Deprecated in Java 1.2</font>
}
}
<font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">void</font> change() {
i++;
update();
}
}
<font color="#0000ff">class</font> Resumer <font color="#0000ff">extends</font> Thread {
<font color="#0000ff">private</font> SuspendResume sr;
<font color="#0000ff">public</font> Resumer(SuspendResume sr) {
<font color="#0000ff">this</font>.sr = sr;
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">try</font> {
sleep(1000);
} <font color="#0000ff">catch</font> (InterruptedException e){}
sr.resume(); <font color="#009900">// Deprecated in Java 1.2</font>
}
}
} <font color="#009900">///:Continued </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SuspendResume1</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
also has a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized
run( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. Again, when you start this thread you’ll see that its associated
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
gets blocked waiting for the lock to become available, which never happens.
This is fixed as before in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SuspendResume2</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which does not
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronize</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the entire
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method but instead uses a separate
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>change( )</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">You
should be aware that Java 1.2<A NAME="Index2555"></A>
deprecates the use of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>resume( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
because
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
holds the object’s lock and is thus <A NAME="Index2556"></A>deadlock-prone.
That is, you can easily get a number of locked objects waiting on each other,
and this will cause your program to freeze. Although you might see them used in
older programs you should not use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>resume( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The proper solution is described later in this chapter.
</FONT><P></DIV>
<A NAME="Heading499"></A><H4 ALIGN=LEFT>
Wait
and notify
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
point with the first two examples is that both
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sleep( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -