我刚从sun的文档中了解到,当我调用thread.stop()方法时,run()方法将在抛出ThreadDeath错误时终止,并且还释放此线程持有的所有锁,如何证明它?
我尝试了我的测试程序,如下所示:
public static void main(String[] args) {
final Object lock = new Object();
try {
Thread t = new Thread() {
public synchronized void run() {
try {
synchronized (lock) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
System.out.println("runing.." + i);
System.out
.println((System.currentTimeMillis() - start) / 1000);
}
} catch (Throwable ex) {
System.out.println("Caught in run: " + ex);
ex.printStackTrace();
}
}
};
t.start();
// Give t time to get going...
Thread.sleep(100);
t.stop(); // EXPECT COMPILER WARNING
} catch (Throwable t) {
System.out.println("Caught in main: " + t);
t.printStackTrace();
}
}
只有当我在run()方法中放入wait()时,我才能捕获ThreadDeath错误,有没有人知道jvm如何处理stop()的详细信息?
public static void main(String[] args) {
final Object lock = new Object();
try {
Thread t = new Thread() {
public synchronized void run() {
try {
synchronized (lock) {
wait();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
System.out.println("runing.." + i);
System.out
.println((System.currentTimeMillis() - start) / 1000);
}
} catch (Throwable ex) {
System.out.println("Caught in run: " + ex);
ex.printStackTrace();
}
}
};
t.start();
// Give t time to get going...
Thread.sleep(100);
t.stop(); // EXPECT COMPILER WARNING
} catch (Throwable t) {
System.out.println("Caught in main: " + t);
t.printStackTrace();
}
}
答案 0 :(得分:5)
简单的答案是jvm没有可靠的方法来阻止线程。要停止或中断线程,目标线程需要通过进入一些可中断状态来配合,例如sleep()或wait()。
由于这个原因(其中包括),不推荐使用Thread.stop()方法。有关详细信息,请参阅http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html。
答案 1 :(得分:4)
我认为我不能比Sun更好地解释。
以下是官方Javadoc的引用:
已弃用。此方法本质上不安全。使用Thread.stop停止一个线程会导致它解锁它已锁定的所有监视器(这是未经检查的ThreadDeath异常向上传播的自然结果)。如果先前受这些监视器保护的任何对象处于不一致状态,则受损对象对其他线程可见,可能导致任意行为。 stop的许多用法应该被简单修改某个变量的代码替换,以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。如果目标threa link text d等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。有关更多信息,请参阅为什么Thread.stop,Thread.suspend和Thread.resume已弃用?。
见这里: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html
答案 2 :(得分:2)
这是因为线程在当前线程退出睡眠之前执行并调用t.stop。
答案 3 :(得分:1)
Thread.stop()不会停止线程。相反,它调用Thread.stop(new ThreadDeath()),它触发线程抛出此错误,默认情况下会默默忽略。即如果你抛出任何其他Throwable,uncaughtException将把它打印到System.err。来自ThreadGroup
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
这个错误没有别的特别/神奇。如果你抛出新的ThreadDeath(),你的线程将以相同的方式展开。为了比较,请尝试
thread.stop(new RuntimeException());
答案 4 :(得分:0)
关于Thread.stop的解释非常正确。构建合作可运行的正确方法如下:
public class MyRunnable implements Runnable {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
public void run() {
// do stuff
if (stopped) {
// cleanup and return;
}
// do more stuff
if (stopped) {
// cleanup and return;
}
}
}
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
r.stop();
t.join(); // if you want to wait for it to die.
OR
public class MyRunnable implements Runnable {
public void run() {
// do stuff
if (Thread.currentThread().isInterrupted()) {
// cleanup and return;
}
// do more stuff
if (Thread.currentThread().isInterrupted()) {
// cleanup and return;
}
}
}
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
t.interrupt();
t.join(); // if you want to wait for it to die.
请注意,在任何一种情况下,您都会在代码中设置策略性停止点,以检查是否应继续处理。第二种方法的优点是可以立即中断基于Thread.sleep和java.nio的I / O操作等中断感知操作,而不必等待停止点。相反,他们会立即抛出InterruptedException(或者在NIO的情况下抛出ClosedByInterruptException)。请注意,基于标准java.io的I / O不能识别中断,您必须等待一个编码停止点。
答案 5 :(得分:-1)
真正的答案是类Thread的stop方法调用同步的私有stop1方法。由于您的线程运行方法的实现也是同步的,因此在退出run方法之前无法输入stop1方法。