为什么thread.stop()不起作用?

时间:2010-12-13 07:25:23

标签: java multithreading

我刚从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();
  }

 }

6 个答案:

答案 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方法。