jdk/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html
2024-07-12 21:50:51 +00:00

162 lines
6.3 KiB
HTML

<!doctype html>
<!--
Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
-->
<html lang="en">
<head>
<title>Java Thread Primitive Deprecation</title>
</head>
<body>
<h1>Java Thread Primitive Deprecation</h1>
<hr>
<h2>Why is <code>Thread.stop</code> deprecated and the ability to
stop a thread removed?</h2>
<p>Because it was inherently unsafe. Stopping a thread caused it to
unlock all the monitors that it had locked. (The monitors were
unlocked as the <code>ThreadDeath</code> exception propagated up
the stack.) If any of the objects previously protected by these
monitors were in an inconsistent state, other threads may have viewed
these objects in an inconsistent state. Such objects are said to be
<i>damaged</i>. When threads operate on damaged objects, arbitrary
behavior can result. This behavior may be subtle and difficult to
detect, or it may be pronounced. Unlike other unchecked exceptions,
<code>ThreadDeath</code> killed threads silently; thus, the user had
no warning that their program may be corrupted. The corruption could
manifest itself at any time after the actual damage occurs, even
hours or days in the future.</p>
<hr>
<h2>Couldn't I have just caught <code>ThreadDeath</code> and fixed
the damaged object?</h2>
<p>In theory, perhaps, but it would <em>vastly</em> complicate the
task of writing correct multithreaded code. The task would be
nearly insurmountable for two reasons:</p>
<ol>
<li>A thread could throw a <code>ThreadDeath</code> exception
<i>almost anywhere</i>. All synchronized methods and blocks would
have to be studied in great detail, with this in mind.</li>
<li>A thread could throw a second <code>ThreadDeath</code> exception
while cleaning up from the first (in the <code>catch</code> or
<code>finally</code> clause). Cleanup would have to be repeated till
it succeeded. The code to ensure this would be quite complex.</li>
</ol>
In sum, it just isn't practical.
<hr>
<h2>What should I use instead of <code>Thread.stop</code>?</h2>
<p>Most uses of <code>stop</code> should be replaced by code that
simply modifies some variable to indicate that the target thread
should stop running. The target thread should check this variable
regularly, and return from its run method in an orderly fashion if
the variable indicates that it is to stop running. To ensure prompt
communication of the stop-request, the variable must be
<code>volatile</code> (or access to the variable must be
synchronized).</p>
<p>For example, suppose your applet contains the following
<code>start</code>, <code>stop</code> and <code>run</code>
methods:</p>
<pre>
private Thread blinker;
public void start() {
blinker = new Thread(this);
blinker.start();
}
public void stop() {
blinker.stop(); // UNSAFE!
}
public void run() {
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
</pre>
You can avoid the use of <code>Thread.stop</code> by replacing the
applet's <code>stop</code> and <code>run</code> methods with:
<pre>
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
</pre>
<hr>
<h2>How do I stop a thread that waits for long periods (e.g., for
input)?</h2>
<p>That's what the <code>Thread.interrupt</code> method is for. The
same "state based" signaling mechanism shown above can be used, but
the state change (<code>blinker = null</code>, in the previous
example) can be followed by a call to
<code>Thread.interrupt</code>, to interrupt the wait:</p>
<pre>
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
</pre>
For this technique to work, it's critical that any method that
catches an interrupt exception and is not prepared to deal with it
immediately reasserts the exception. We say <em>reasserts</em>
rather than <em>rethrows</em>, because it is not always possible to
rethrow the exception. If the method that catches the
<code>InterruptedException</code> is not declared to throw this
(checked) exception, then it should "reinterrupt itself" with the
following incantation:
<pre>
Thread.currentThread().interrupt();
</pre>
This ensures that the Thread will reraise the
<code>InterruptedException</code> as soon as it is able.
<hr>
<h2>What if a thread doesn't respond to
<code>Thread.interrupt</code>?</h2>
<p>In some cases, you can use application specific tricks. For
example, if a thread is waiting on a known socket, you can close
the socket to cause the thread to return immediately.
Unfortunately, there really isn't any technique that works in
general. <em>It should be noted that in all situations where a
waiting thread doesn't respond to <code>Thread.interrupt</code>, it
wouldn't respond to <code>Thread.stop</code> either.</em> Such
cases include deliberate denial-of-service attacks, and I/O
operations for which thread.stop and thread.interrupt do not work
properly.</p>
</body>
</html>