【问题标题】:Java - Close a thread with 'return' not workingJava - 用“return”关闭线程不起作用
【发布时间】:2015-05-15 19:22:14
【问题描述】:

我在一个包含我的main 方法的类中有以下代码

ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
System.out.println("Called an instance of formatConcentration");
while (!executor.isTerminated())
{
    //stay Alive
    Thread.sleep(1000);
    System.out.println("Still alive");
}
System.out.println("Program successfully finished");
return;

这会创建一个formatConcentration 类的实例。代码如下(为了示例,我删除了所有功能)。

public class formatConcentration extends Thread{
    private int numberOfNewRows;

    formatConcentration(int rows)
    {
        this.numberOfNewRows = rows;
    }
    public void run() {

        System.out.println("Running the Formatting Script");
        final int numberOfNewRegistered = this.numberOfNewRows;
        try 
        {
            System.out.println("Finished formatting");
        }//end of try
        catch (Exception e1) 
        {
            log.log(e1.toString());
            log.closeLog() ;
            System.exit(1) ;
        }
        System.out.println("Still Finished formatting");
        return;
    }
}

我的问题是,一旦return 被调用,它不会终止线程。

我已经做了很多环顾四周,据我所知这应该没问题,但我想我忽略了一些小东西,希望能以新的眼光看待这个问题。

或者,如果有人建议如何从 run(){} 方法中杀死线程,我将不胜感激(最好不要设置我将在主类中检查的变量,但如果我必须这样做就这样吧)因为我知道,一旦它到达返回语句,它就完成了,不再需要对run()中创建的变量的任何引用。

生成到控制台的输出如下:

Called an instance of formatConcentration
Running the Formatting Script
Finished formatting
Still Finished formatting
Still alive
Still alive
Still alive
Still alive
Still alive
etc.

【问题讨论】:

  • executor.shutdown();在此之前

标签: java multithreading terminate


【解决方案1】:

您永远不会关闭executor。来自isTerminated 的 Javadocs:

如果所有任务在关闭后都已完成,则返回 true。请注意,除非先调用了 shutdown 或 shutdownNow,否则 isTerminated 永远不会为真。

只要不关闭executor,就可以提交新任务给它执行。 isTerminated 检查提交任务的状态,它检查 ExecutorService 本身的状态。

【讨论】:

    【解决方案2】:
    ExecutorService executor = Executors.newFixedThreadPool(1);
    Runnable formatConcentration = new formatConcentration(87);
    executor.execute(formatConcentration);
    System.out.println("Called an instance of formatConcentration");
    executor.shutdown();
    while (!executor.isTerminated())
    {
        //stay Alive
        Thread.sleep(1000);
        System.out.println("Still alive");
    }
    System.out.println("Program successfully finished");
    return;
    

    另一种更简单的方法是:

       ExecutorService executor = Executors.newFixedThreadPool(1);
        Runnable formatConcentration = new formatConcentration(87);
        executor.execute(formatConcentration);
        executor.shutdown();
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    

    Executor awaitTermination 方法替代您的循环。

    【讨论】:

    • 我将使用您的第二个解决方案。只是出于好奇,因为您调用“executor.shutdown();”在“while(!executor.isTerminated())”之前它不会在进入while循环之前总是关闭吗?因此,由于它不是一个守护线程,它不会关闭,直到所有资源都被交还,使得 while 循环在执行程序处于活动状态时无法访问?
    • 您调用了 shutdown 方法,但该方法不会等待执行程序终止所有线程。关闭调用后继续执行。所以它会进入while循环,如果线程需要更长的时间来执行它会做几个循环。这就是为什么如果你想在关机后等待,你可以调用 awaitTermination,它与循环基本相同,但在代码中更清晰。
    • 最后一件事 - 使用大写字母作为类名;)
    • 感谢您简洁明了的解释。如果我有特权,我会 +1 编辑:哈哈约定,我会做出适当的更改;)
    【解决方案3】:

    ExecutorService 主要用于将您的工作委派给单独的工作人员。 仅使用它创建了大多数连接池库。 因此,该服务将在您的应用程序启动时启动,并由您的应用程序的关闭方法(手动)关闭。

    在你的程序中你应该写一个代码来检查执行器服务的状态,

    目前是否有工人在工作... 如果没有工作人员处于忙碌模式,则停止接受任何进一步的任务。

    从 javadocs 查看示例关闭代码,

    以下方法分两个阶段关闭一个ExecutorService,首先调用shutdown拒绝传入的任务,然后在必要时调用shutdownNow取消任何延迟的任务:

    void shutdownAndAwaitTermination(ExecutorService pool) {
       pool.shutdown(); // Disable new tasks from being submitted
       try {
         // Wait a while for existing tasks to terminate
         if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
           pool.shutdownNow(); // Cancel currently executing tasks
           // Wait a while for tasks to respond to being cancelled
           if (!pool.awaitTermination(60, TimeUnit.SECONDS))
               System.err.println("Pool did not terminate");
         }
       } catch (InterruptedException ie) {
         // (Re-)Cancel if current thread also interrupted
         pool.shutdownNow();
         // Preserve interrupt status
         Thread.currentThread().interrupt();
       }
     }
    

    希望能给你一些信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多