【问题标题】:How to stop uninterruptible threads in Java如何在 Java 中停止不间断线程
【发布时间】:2010-12-29 17:48:11
【问题描述】:

我有一个 我无法编辑的 Java 应用程序,它启动了一个具有此 run() 方法的 java.lang.Thread

public void run(){
   while(true){
     System.out.println("Something");
   }
}

在某个时间点我想停止它。如果我使用Thread.interrupt() 它不起作用。 如果我使用Thread.stop(),它可以工作,但这种方法已被弃用(因此不鼓励使用它,因为它可能会在新版本中从 JVM 中删除)。

如何在 Java 中停止这种不间断的线程?

【问题讨论】:

标签: java multithreading


【解决方案1】:

java 调试器将允许您通过向线程中注入异常来终止线程。

启动您的 Java 进程并让它监听某个端口:

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4444 <Your Program>

并将调试器与以下内容连接:

jdb -attach 127.0.0.1:4444

并发出以下命令:

threads

获取正在运行的线程列表,并使用 kill 命令杀死正在运行的线程。

kill 0xe2e new java.lang.IllegalArgumentException("er");

【讨论】:

    【解决方案2】:

    在此链接下:http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html:

    如果线程没有响应 Thread.interrupt 怎么办?

    在某些情况下,您可以使用特定于应用程序的技巧。例如,如果一个线程在一个已知的套接字上等待,您可以关闭该套接字以使该线程立即返回。不幸的是,实际上没有任何技术可以通用。 需要注意的是,在等待线程不响应 Thread.interrupt 的所有情况下,它也不会响应 Thread.stop。 这种情况包括故意拒绝服务攻击,以及 thread.stop 和 thread.interrupt 无法正常工作的 I/O 操作。

    【讨论】:

      【解决方案3】:

      如果没有线程的合作,您无法可靠地中断线程。

      作为一个丑陋的 hack(不实用!),您可以替换 System.out 并使 println 在满足中断条件并且相关线程是当前线程时抛出异常(即,将其用作挂钩)在目标线程的上下文中提供一些合作)。

      编辑: 更优雅的选项 - 当 Thread.interrupted()true 时,您可以通过引发异常来使 println 可中断,以便可以通过调用 thread.interrupt() 来中断线程。

      这个方法的语义将非常接近普通的可中断方法(即抛出InterruptedException的方法),虽然你不能使用InterruptedException,因为它是一个已检查的异常,需要使用未检查的RuntimeException来代替:

      System.setOut(new PrintStream(System.out) {
          public void println(String s) {
              if (Thread.interrupted()) throw new RuntimeException();
              super.println(s);
          }
      });
      

      【讨论】:

      • 对这个答案投反对票的人能否提供投反对票的理由?
      • 这就是我要做的,System.setOut() 使用你自己的流,它要么关闭流,要么在你完成后抛出。当您希望线程退出时,您甚至可以更加精确,因为您将能够处理所有文本。
      • 如果您可以替换任何东西来处理(挂钩)调用,您可以随时检查线程是否需要经过(我抛出ThreadDeath),您有Thread.currentThread(),您可以随时检查一个ThreadLocal(可能需要使用initialValue()),它指向持有特定状态的AtomicInteger。我,我自己,倾向于钩住记录器——它们是一个完美的基于 API 的目标。有时由于try{}catch(Throwable t) 构造和标志丢失,很难通过中断。
      【解决方案4】:

      您可以使用检查变量来实现中断方法。

      首先使用 volatile 检查变量作为:

      volatile boolean tostop = false; // Keep the initial value to be false
      

      接下来定义你的线程依赖于这个变量。

      Thread thread1 = new Thread(){
          public void run() {
              while(!tostop) {
               -- Write your code here --
              }
           }
       }
      

      接下来定义使用线程的函数:

      public void ....{
          //Interrupt code
          tostop = true;
          thread1.sleep(300);  // Give the thread sometime for cleanup
          //Use System.exit(0), if the thread is in main function.
      }
      

      希望这会有所帮助。

      【讨论】:

      • 我认为 Dr.Lesh 无法编辑代码!您可能也应该更喜欢 while (!Thread.currentThread().isInterruptted()) 而不是检查变量...并为清理而睡觉?真的吗?
      • @venomrld 如果您知道您的回答我们错了,为什么不更正或删除它?
      • 不好的答案,显然你可以这样做,如果你控制线程但如果线程已经制作或者如果它是 nio fs read 那么你被这个“答案”搞砸了
      【解决方案5】:

      我不知道有任何已从 JRE 中删除的过时方法。 stop() 已被弃用很长时间,可能超过 10 年。使用它是个坏主意,但它可能是您的最佳选择。

      【讨论】:

        【解决方案6】:

        好的,我找到了解决方案,而且真的很简单,只需休眠线程然后中断它!

        final Thread t = getTheThreadToClose();
        
        //Final is important because only in this way you can pass it to the following new Thread
        
        if (t != null && t.isAlive() && !t.isInterrupted()){
            try{
               new Thread(){
                   public void run(){
                       try{ 
                          t.sleep(3000);//SLEEP INSIDE THE NEW THREAD
                       }
                       catch(InterruptedException ex){}
                   }
               }.start();
        
               t.interrupt();//INTERRUPT OUTSIDE THE NEW STARTED THREAD
            }
            catch(Exception e){}
        }
        

        它适用于所有情况!

        我要感谢你们所有人的真正有用的帮助,尤其是 venomrld 和 Toby,他们用他们的话给了我解决方案的灵感 ;-),以及这个奇妙的网站,它让我总是能解决我所有的编程问题。

        再次感谢大家,新年快乐!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-31
          相关资源
          最近更新 更多