【问题标题】:Java Thread.stop() vs Thread.interrupt()Java Thread.stop() 与 Thread.interrupt()
【发布时间】:2013-12-11 19:09:16
【问题描述】:

我有以下代码:

renderThread = new Thread(new Runnable() {

    @Override
    public void run() {
        for (int i = 0; i < 10000000; i++) {
            System.out.println("Number: " + i);
        }
    }
});

renderThread.start();

try {
    Thread.sleep(100);
} catch (InterruptedException ex) {
    ex.printStackTrace();
}

renderThread.interrupt(); //It should stop, but it does not stop.

renderThread.interrupt() 不会中断线程,它会继续运行。如果我用.stop() 替换renderThread.interrupt(),那么线程就会停止。但是,.stop() 已被弃用。 那么,如果 stop 已被弃用且 interrupt 不起作用,那么停止线程的正确方法是什么?

【问题讨论】:

  • 为什么你认为调用interrupt停止线程`?
  • @SotiriosDelimanolis 因为通俗地说,“打断某事”和“停止某事”是同义词.. 我不是说它是 所做的 (文档很好开始展开假设的地方),但名称已加载。

标签: java multithreading


【解决方案1】:

当你调用 interrupt() 时,它会触发一个布尔标志,告诉 run 函数它应该停止。这就是为什么我通常这样编写我的运行函数。

void run()
{
    while(!Thread.interrupted())
    {
        //Do something
    }
}

仅仅因为您调用了中断并不意味着线程将立即或完全停止。这取决于 run 函数中的内容。

【讨论】:

  • 那么就是说,在中断事件发生后,代码到达run()的末尾,那么线程就自动不存在了?
  • 是的。据我所知,线程应该只在运行退出时停止。中断运行只是让它知道它应该尽快退出。调用 stop() 的问题是说 run() 必须做一些清理,比如关闭一个流,然后这不会发生。
  • 我认为这个解决方案不能解决这里的问题。当renderThread执行任务时,没有机会去检查Thread.interrupted()。
  • 如果你的线程中有sleep方法,你将不得不在try...catch (InterruptedException)的这个线程中调用interrupt方法:stackoverflow.com/a/36258705/7767664
【解决方案2】:

要真正强调为什么不应该使用Thread.stop()

Doug Lea 最近提到 Thread.stop 将是Java 8 中第一个取消实现的方法

他对某人的评论的回应:

此外,同步的另一件事是它可以处理 异步中止线程(即 thread.stop())。我知道 stop() 是 已弃用,但你永远不知道。

曾经:

但你知道!从 JDK8 开始,Thread.stop 真的消失了。它是 第一个不推荐使用的方法实际上已被取消实现。现在它 只是抛出 UnsupportedOperationException。

http://cs.oswego.edu/pipermail/concurrency-interest/2013-December/012028.html

【讨论】:

    【解决方案3】:

    你应该看看这篇文章: http://10kloc.wordpress.com/2013/03/03/java-multithreading-steeplechase-stopping-threads/

    基本上你不应该停止线程(不安全),而是中断它。 你缺少的是让线程处理中断。

    【讨论】:

      【解决方案4】:

      中断当前线程或终止线程正在运行的进程所需要做的就是 在你的 catch 块中添加以下语句

      try
      {
         Thread.sleep(4000);
         System.out.println("VAS CONSULTING")
      }
      catch(InterruptedException e)
      {
         //Stop printing out VAS CONSULTING
         return;  /*This will terminate the thread*/
      }
      

      如果在 run 方法中没有使用不抛出中断异常的方法 你可以这样做来处理线程中断或终止线程

      @Override
      public void run()
      {
      
         System.out.println("VAS CONSULTING");
         if(Thread.Interrupted())
         {
           doSomethingElse();//process something else within the thread
          return; //Terminates the current Thread
         }
      
      }
      

      我希望这对您或其他人有所帮助。

      【讨论】:

        【解决方案5】:

        renderThread.interrupt() 不会中断线程,它会继续 运行。

        • 如果线程正在执行并且interrupt() 被调用,它的中断状态被设置。
        • 如果此线程在调用 Object 类的 wait 方法之一或此类的 Thread.joinThread.sleep 方法之一时被阻塞,则其中断状态将被清除它会收到一个InterruptedException

        例如:

        Thread t = new Thread()
              {
                  public void run()
                  {
                      try {
                          for(int i=0; i<10000;i++)
                              System.out.println("Is interrupTed? "+this.isInterrupted());
        
                          Thread.sleep(200);
                      } catch (InterruptedException ex) {
                          Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
                      }
        
                  }
              };
              t.start();
              t.interrupt();
            }
        

        上面的代码,我用for循环拦截了带有isInterrupted()函数的interrput标志并打印出来。在调用t.interrupt() 时,isInterrupted() 将返回您将在控制台中看到的true。一旦它到达Thread.sleep(miliTime),您将看到InterruptedException 被捕获,如上所述被抛出。

        停止线程:

        您可以使用此isInterrupted() 标志检查是否在其上调用了interrupt() 并从执行中返回:

        例如:

        Thread t = new Thread()
              {
                  public void run()
                  {
                      long executeTime = System.currentTimeMillis() ;
                      int i = 0;    
                      for(; i<10000 && !this.isInterrupted();i++)
                              System.out.println("Is interrupted? "+this.isInterrupted());
        
                       System.out.println("Was Interrupted? "+this.isInterrupted()
                                          +" after cycle: "+ i);
                       System.out.println("Time it gets Executed: "
                                          +(System.currentTimeMillis() - executeTime+" ms"));
        
                  }
              };
              t.start();
                try {
                    Thread.sleep(200);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
              t.interrupt();
        

        在运行上述代码时:我已将主线程发送到静态主函数内的200 休眠,以允许启动的线程t 运行一段时间。然后我在其上调用
        t.interrupt() 导致for 循环停止并打印如下输出:

        Was Interrupted? true after cycle: 1477
        Time it gets Executed: 258 ms
        

        这表明for 循环在t.interrupt();main 函数调用之前进行了1148 迭代。

        请阅读Thread.interrupt()函数的文档了解更多详情。

        【讨论】:

          【解决方案6】:

          interrupt() 方法不会停止线程。 阅读本文以获得更详细的解释http://www.ibm.com/developerworks/java/library/j-jtp05236/

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-07-05
            • 1970-01-01
            • 2013-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多