【问题标题】:How is an executor terminated in my Java program?我的 Java 程序中的执行程序是如何终止的?
【发布时间】:2014-06-23 22:37:59
【问题描述】:

这个问题和我之前的问题有关:Why the speed of a Java process inside multiple loops slows down as it goes?

为了找到那个问题的问题,我仔细查看了我的代码,发现我的应用程序中的一些执行器没有被终止,因为我正在学习如何使用执行器,所以我复制了一些在线示例代码并在我的应用程序中使用它们,我不确定我是否正确使用它们。

以下两种使用执行器的方法有什么区别?

[1]

 Executor executor=Executors.newFixedThreadPool(30);
 CountDownLatch doneSignal=new CountDownLatch(280);

 for (int N=0;N<280;N++)
 {
   ...
   executor.execute(new SampleCountRunner(doneSignal,...));
 }
 try { doneSignal.await(); }
 catch (Exception e) { e.printStackTrace(); }

[2]

ExecutorService executor=Executors.newFixedThreadPool(30);

for (int i=0;i<60;i++)
{
  ...
  executor.execute(new xyzRunner(...));
}
executor.shutdown();

while (!executor.isTerminated()) { }

在我看来,在第一个完成后,执行程序仍然有一个活动线程池正在运行并等待更多任务,它们确实会消耗 cpu 时间和内存。

第二个将在shutdown()方法运行后终止池中的所有活动线程,并且在此之后所有以前活动的线程将不再占用cpu时间或内存。

所以我的问题是:

[1] 我说的对吗?

[2] 第一种情况如何终止线程池? Executor 没有“executor.shutdown()”

编辑:

问题解决了,我将[1]中的Executor改为ExecutorService,并补充:

   executor.shutdown();
   while (!executor.isTerminated()) { }

现在当我的程序结束时,它不会再有很多活动线程了。

【问题讨论】:

    标签: java executorservice executor


    【解决方案1】:

    在我看来,在第一个完成后,执行程序仍然有一个活动线程池正在运行并等待更多任务,它们确实会消耗 cpu 时间和内存。

    不完全是。在第一种方法中,在任务全部完成后(由锁存器发出信号),执行程序肯定不会关闭 - 但执行程序中的线程不会消耗 cpu(它们消耗它们的结构所需的最小内存是的)。

    在这种方法中 - 您可以明确控制知道何时以及如何完成您的任务。您可以知道任务是成功还是失败,并且可以根据需要决定重新提交任务。

    第二个将在shutdown()方法运行后终止池中的所有活动线程,并且在此之后所有以前活动的线程将不再占用cpu时间或内存。

    同样,不完全是。在这种方法中,ExecutorService 在调用shutdown() 后不会立即关闭。它等待已经提交的任务完成,但在这里你不能直接知道这些任务是成功完成还是失败(通过抛出一些Exception)。

    在已经提交的任务完成之前 - 你的 isShutDown() 将执行一个紧密的循环(它会将 cpu 飙升到接近 100%)。

    【讨论】:

    • 第二个问题的答案是什么?
    • 好吧 - 只需使用 ExecutorService 代替普通的 Executor。或者干脆将其转换为ExecutorService,这必然会成功,因为调用Executors.newFixedThreadPool(30); 总是返回一个ExecutorService 的实例。
    【解决方案2】:

    线程池(ExecutorService)一般来说不应该定期创建/销毁。相反,它们应该长期存在(可能是应用程序的整个生命周期)以避免线程创建/销毁的(显着)开销。

    如果您想提交任务列表并等待所有任务完成,请使用ExecutorService.invokeAll(),而不是尝试通过倒计时锁存器跟踪完成情况。

    ExecutorService 接口提供 2 种关闭机制:shutdownshutdownNow。第一个简单地停止接受新工作,并在当前正在执行和已经提交的工作完成时停止线程。第二个将尝试中断所有正在进行的工作,甚至不会处理已提交但尚未开始的作业。

    【讨论】:

      猜你喜欢
      • 2016-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多