使用Java执行器的正确方法是什么?

时间:2015-07-24 14:09:22

标签: java executor

我正在以下列方式使用Java执行器,但不确定每行是否必要,以及这是否正确使用它:

  ExecutorService executor=Executors.newFixedThreadPool(30);
...
  int N=200;
  CountDownLatch doneSignal=new CountDownLatch(N);
  for (int i=0;i<N;i++) executor.execute(new Test_Runner(doneSignal,...));
  doneSignal.await();
  executor.shutdown();
  while (!executor.isTerminated()) { Thread.sleep(1000); }
  // Blocks until all tasks have completed execution after a shutdown request
  executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
...

class Test_Runner implements Runnable
{
  private CountDownLatch doneSignal;
  Thread Test_Runner_Thread;

  public Tes_Runner(CountDownLatch doneSignal,...)
  {
    this.doneSignal=doneSignal;
  }

// Define some methods

  public void run()
  {
    try
    {
//      do some work
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    doneSignal.countDown();
  }

  public void start()
  {
    if (Test_Runner_Thread==null)
    {
      Test_Runner_Thread=new Thread(this);
      Test_Runner_Thread.setPriority(Thread.NORM_PRIORITY);
      Test_Runner_Thread.start();
    }
  }

  public void stop() { if (Test_Runner_Thread!=null) Test_Runner_Thread=null; }
}

2 个答案:

答案 0 :(得分:1)

对我来说是正确的。在过去,我遵循了Java 7 JavaDoc for ExecutorService的建议实现来停止它。您可以从Java 7 Javadoc获得它,但为方便起见,我在下面提供它。编辑它以满足您的需求,例如您可能希望传递等待的秒数。使用CountDownLatch的好处是,等待它时,您知道ExecutorService将立即终止。此外,您可能希望在未来的真实案例中为您的锁存器添加超时等待时间。另外,在现实世界的应用程序中使用时,将latch.countDOwn()置于try终端块中。

 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();
   }
 }

答案 1 :(得分:1)

您可以进一步简化代码。

  1. 您可以删除CountDownLatch
  2. 将Test_Runner更改为Callable任务。
  3. 创建Callable任务的ArrayList。

      List<Test_Runner> callables = new ArrayList<Test_Runner>();
      for (int i=0;i<N;i++) {
         callables.add(new Test_Runner());
      }
    
  4. 在executorService上使用invokeAll()

    List<Future<String>> futures = executorService.invokeAll(callables);
    
  5. 来自javadocs,

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
                              throws InterruptedException
    
      

    执行给定的任务,在完成所有任务后返回持有其状态和结果的Futures列表。对于返回列表的每个元素,Future.isDone()都为true。请注意,已完成的任务可能正常终止或通过抛出异常终止。如果在此操作正在进行时修改了给定集合,则此方法的结果未定义。

    您可以按照Jose Martinez的建议关闭executorService

    相关SE问题:How to shutdown an ExecutorService?