如何在我的Java程序中终止执行程序?

时间:2014-06-23 22:37:59

标签: java executorservice executor

此问题与我之前的问题有关: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()) { }

现在,当我的程序结束时,它将不再有很多线程处于活动状态。

2 个答案:

答案 0 :(得分:3)

  

在第一个完成之后,我觉得执行程序仍然有一个活动的线程池在运行并等待更多任务,它们会消耗CPU时间和内存。

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

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

  

第二个将在shutdown()方法运行后终止池中的所有活动线程,并且所有先前活动的线程在该点之后不再需要CPU时间或内存。

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

在完成已提交的任务之前 - 您的isShutDown()将执行紧急循环(它会使cpu达到接近100%)。

答案 1 :(得分:1)

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

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

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