【问题标题】:How stop thread with infinite loop in finally block如何在 finally 块中停止具有无限循环的线程
【发布时间】:2014-10-13 10:23:38
【问题描述】:

对不起我的英语。

我有一个带有方法的线程:

  @Override
  public void run()
  {
    try
    {
      System.out.println( "Hello world" );
      Thread.sleep( 10 );
    }
    catch( InterruptedException e )
    {
      e.printStackTrace();
    }
    finally
    {
      while( true )
        System.out.println( "FINALLYYY" );
    }
  }

我建议,这个线程永远无法停止! 调用方法后中断或停止-finally块中的线程将开始无限循环。

如何强制线程停止?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    线程停止和中断方法并不是解决这个问题的最好方法。在您的线程中添加一个布尔变量并在您的 while 语句中检查它。

    例如:

      private volatile boolean keepGoing = true;
    
      public void stopTheThread() {
          keepGoing = false;
      }
    
      @Override
      public void run()
      {
        try
        {
          System.out.println( "Hello world" );
          Thread.sleep( 10 );
        }
        catch( InterruptedException e )
        {
          e.printStackTrace();
        }
        finally
        {
          while( keepGoing )
            System.out.println( "FINALLYYY" );
        }
      }
    

    【讨论】:

    • 如果你不将 volatile 放在 keepGoing 变量中,你的循环可能永远不会结束。
    • @David ten Hove 是的,我知道......但我无法控制或验证代码......因为它是“外部自定义用户代码”,应该在我们的服务器上执行..
    • @EugeneChipachenko 如果是这样的话,我认为在 Java 中没有停止线程的可靠方法
    • @CarlosVerdes 不错。我错过了
    【解决方案2】:

    所以... 我找到了下一个解决方案:

    worker.interrupt();
    while( worker.isAlive() )
      worker.stop();
    

    这不是理想的解决方案,但就我而言,这是最好的... 每次调用 worker.stop - 抛出未经检查的异常“ThreadDeath”并且每个 finally 块都将被“跳过”。 它应该停止线程。

    【讨论】:

      【解决方案3】:

      在您当前的设置中,您可以通过在正在执行的Thread 上调用interrupt() 方法来停止线程。

      无论哪种方式,要让线程正常终止,您都必须公开一种终止该线程的方法,或者通过公开线程使其可以被中断,或者按照建议的方式提供“终止开关”大卫十霍夫。

      【讨论】:

        【解决方案4】:
        1. 您可以尝试控制用户线程的执行方式(至少在您控制用户线程执行的同时)。例如,您可以使用并发包中的 Future(不要忘记处理异常):

           ExecutorService executor = Executors.newSingleThreadExecutor();
           Future task = executor.submit(usersThread);
          
           try {
               task.get(1, TimeUnit.MINUTES);
           } finally {
               task.cancel(true);
           }
          
        2. 如果你不能控制线程内部的代码,那么你可以控制它使用的代码。例如,考虑以下方法:

          • 如果您可以在 groovy 上下文中运行该线程,那么您可以重新分配从线程调用的方法。实际上,您可以拒绝一切,并通过您的自定义处理程序为未知方法传递每个调用。
          • 如果您确定从 Thread 调用的内容,那么您可以选择一些劫持(考虑 this question 中的示例)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-03
          • 2018-11-19
          • 2014-01-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多