📄 tij0157.html
字号:
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">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>init( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
notice the loop that moves through the entire array and adds the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>state</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>peeker.status</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
text fields to the page.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blockable
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">threads
are initially created, each one automatically creates and starts its own
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
So you’ll see the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
running before the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blockable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
threads are started. This is essential, as some of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Peeker</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
will get blocked and stop when the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blockable</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
threads start, and it’s essential to see this to understand that
particular aspect of blocking.
</FONT><a name="_Toc375545483"></a><a name="_Toc408018757"></a><P></DIV>
<A NAME="Heading502"></A><H3 ALIGN=LEFT>
Deadlock<P><A NAME="Index2569"></A><A NAME="Index2570"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Because
threads can become blocked
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>and</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
because objects can have
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>synchronized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods that prevent threads from accessing that object until the
synchronization lock is released, it’s possible for one thread to get
stuck waiting for another thread, which in turn waits for another thread, etc.,
until the chain leads back to a thread waiting on the first one. Thus,
there’s a continuous loop of threads waiting on each other and no one can
move. This is called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>deadlock</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The claim is that it doesn’t happen that often, but when it happens to
you it’s frustrating to debug.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">There
is no language support to help prevent deadlock; it’s up to you to avoid
it by careful design. These are not comforting words to the person who’s
trying to debug a deadlocking program.
</FONT><P></DIV>
<A NAME="Heading503"></A><H4 ALIGN=LEFT>
The
deprecation of stop( ), suspend( ),
<P>resume( ),
and destroy( ) in Java 1.2
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
change that has been made in Java 1.2<A NAME="Index2571"></A>
to reduce the possibility of deadlock is the deprecation of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’s
<A NAME="Index2572"></A><A NAME="Index2573"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>stop( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
<A NAME="Index2574"></A><A NAME="Index2575"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
<A NAME="Index2576"></A><A NAME="Index2577"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>resume( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>destroy( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
reason that the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>stop( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
<A NAME="Index2578"></A><A NAME="Index2579"></A>method
is deprecated is because it is unsafe. It releases all the locks that the
thread had acquired, and if the objects are in an inconsistent state
(“damaged”) other threads can view and modify them in that state.
The resulting problems can be subtle and difficult to detect. Instead of using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>stop( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you should follow the example in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blocking.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and use a flag to tell the thread when to terminate itself by exiting its
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>run( )</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">There
are times when a thread blocks, such as when it is waiting for input, and it
cannot poll a flag as it does in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blocking.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In these cases, you still shouldn’t use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>stop( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but instead you can use the <A NAME="Index2580"></A><A NAME="Index2581"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interrupt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method in <A NAME="Index2582"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to break out of the blocked code:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Interrupt.java</font>
<font color="#009900">// The alternative approach to using stop()</font>
<font color="#009900">// when a thread is blocked</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> Blocked <font color="#0000ff">extends</font> Thread {
<font color="#0000ff">public</font> <font color="#0000ff">synchronized</font> <font color="#0000ff">void</font> run() {
<font color="#0000ff">try</font> {
wait(); <font color="#009900">// Blocks</font>
} <font color="#0000ff">catch</font>(InterruptedException e) {
System.out.println("InterruptedException");
}
System.out.println("Exiting run()");
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Interrupt <font color="#0000ff">extends</font> Applet {
<font color="#0000ff">private</font> Button
interrupt = <font color="#0000ff">new</font> Button("Interrupt");
<font color="#0000ff">private</font> Blocked blocked = <font color="#0000ff">new</font> Blocked();
<font color="#0000ff">public</font> <font color="#0000ff">void</font> init() {
add(interrupt);
interrupt.addActionListener(
<font color="#0000ff">new</font> ActionListener() {
<font color="#0000ff">public</font>
<font color="#0000ff">void</font> actionPerformed(ActionEvent e) {
System.out.println("Button pressed");
<font color="#0000ff">if</font>(blocked == <font color="#0000ff">null</font>) <font color="#0000ff">return</font>;
Thread remove = blocked;
blocked = <font color="#0000ff">null</font>; <font color="#009900">// to release it</font>
remove.interrupt();
}
});
blocked.start();
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Interrupt applet = <font color="#0000ff">new</font> Interrupt();
Frame aFrame = <font color="#0000ff">new</font> Frame("Interrupt");
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(200,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">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>wait( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Blocked.run( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
produces the blocked thread. When you press the button, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>blocked</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle is set to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so the garbage collector will clean it up, and then the object’s
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interrupt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is called. The first time you press the button you’ll see that the
thread quits, but after that there’s no thread to kill so you just see
that the button has been pressed.
</FONT><P></DIV><DIV ALIGN=LEFT><A NAME="Index2583"></A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</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">
methods turn out to be inherently deadlock-prone. When you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>suspend( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the target thread stops but it still holds any locks that it has acquired up to
that point. So no other thread can access the locked resources until the thread
is resumed. Any thread that wants to resume the target thread and also tries to
use any of the locked resources produces deadlock. 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">,
but instead put a flag in your
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class to indicate whether the thread should be active or suspended. If the flag
indicates that the thread is suspended,<A NAME="Index2584"></A><A NAME="Index2585"></A><A NAME="Index2586"></A><A NAME="Index2587"></A>
the thread goes into a wait using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>wait( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
When the flag indicates that the thread should be resumed the thread is
restarted with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>notify( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
An example can be produced by modifying
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Counter2.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Although the effect is similar, you’ll notice that the code organization
is quite different – <A NAME="Index2588"></A><A NAME="Index2589"></A><A NAME="Index2590"></A>anonymous
inner classes are used for all of the listeners and the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Thread</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is an inner class, which makes programming slightly more convenient since it
eliminates some of the extra bookkeeping necessary in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Counter2.java</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Suspend.java</font>
<font color="#009900">// The alternative approach to using suspend()</font>
<font color="#009900">// and resume(), which have been deprecated</font>
<font color="#009900">// in Java 1.2.</font>
<font co
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -