前言
Thread的实例方法stop()用来中止线程,它是真正的中止线程,与之相对应的interrupt()是一种提示性中止,因为没有留出机会让程序员处理资源,stop()会带来状态一致性问题,所以已不推荐使用,不过这里是为了探究为什么不推荐使用,所以研究。
中止线程
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("begin");
try {
this.stop();
} catch (ThreadDeath e) {
System.out.println("进入catch块了");
e.printStackTrace();
}
System.out.println("end");
}
}
public class StopRun {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
}
}
输出结果
java.lang.ThreadDeath
at java.lang.Thread.stop(Thread.java:850)
at extthread.MyThread.run(MyThread.java:13)
begin
进入catch块了
end
根据java api所述,
无论该线程在做些什么,它所代表的线程都被迫异常停止,并抛出一个新创建的 ThreadDeath 对象,作为异常。
通过输出可以看到的确抛出了ThreadDeath,以上示例是参考《Java多线程编程核心技术》一书所写,在实践中我稍微改了一下却发现,没有任何异常信息。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
public class StopRun {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
//让myThread得到机会运行
Thread.sleep(200);
myThread.stop();
}
}
此种写法,控制台什么也没输出!当时我就纳闷了?不应该呀,按照api,stop()方法肯定会抛出ThreadDeath。后来一想,抛出的异常应该在目标线程抛出,而非执行线程抛出,在本例中myThread是目标线程,主线程是执行线程。果断将MyThread的run()方法,try catch,经此一改,果然出现异常信息了
@Override
public void run() {
try {
System.out.println("begin");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}catch (ThreadDeath e){
e.printStackTrace();
}
System.out.println("end");
}
输出结果
begin
java.lang.ThreadDeath
at java.lang.Thread.stop(Thread.java:850)
at test.StopRun.main(StopRun.java:14)
end
ThreadDeath
顺便提一下ThreadDeath,按照api规定,stop()时会抛出ThreadDeath,ThreadDeath是继承自Error,而非Exception子类,通常情况下,是不需要catch的,上边的例子只是为了演示,所以catch。所以在catch时,应该catch(Error)或者catch(ThreadDeath),而不应该catch(Exception),catch(Exception)也不会打印异常信息。
状态一致性问题
stop()属于暴力强制中止线程,会带来状态一致性问题。
public class SynchronizedObject {
private String userName = "a";
private String password = "aa";
public synchronized void printString(String userName, String password){
try {
this.userName = userName;
Thread.sleep(100000);
this.password = password;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class SynchronizedThread extends Thread {
private SynchronizedObject object;
public SynchronizedThread(SynchronizedObject object) {
this.object = object;
}
@Override
public void run() {
object.printString("b","bbb");
}
}
public static void main(String[] args) throws InterruptedException {
SynchronizedObject object = new SynchronizedObject();
SynchronizedThread t = new SynchronizedThread(object);
t.start();
Thread.sleep(500);
t.stop();
System.out.println(object.getUserName()+"-"+object.getPassword());
}
输出结果,可以看到因为stop()的强制中止,没有给程序员预留善后空间,导致状态不一致;理论上,使用stop()的地方都应该使用interrupt()代替;
b-aa
参考
java多线程编程核心技术 高洪岩著