0

我已经使用 ExecutorService 实现了 TimeoutTask。在下面的方法中,我提交了 TimeoutTask,如果它在给定时间内超时,我取消任务并关闭执行程序。

private boolean waitForProcessToBeCompleted(long timeOut) {
            boolean result = false;
            ExecutorService executor = Executors.newSingleThreadExecutor();
            // Create a FutureTask which will be run
            FutureTask<Boolean> futureTask = new FutureTask<Boolean>(new TimeoutTask());
            executor.submit(futureTask); // Run the FutureTask
            try {
                result = futureTask.get(timeOut, TimeUnit.MILLISECONDS); // Check if FutureTask completed in the given time
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                futureTask.cancel(true);
                result = true;  // Return True only when timed out
            } finally {
                executor.shutdownNow(); // Stop the executor
            }
            return result;
        }

它运行得很好,我没有任何问题。

但是,我想知道这是否是最好的代码设计。我只是想知道使用 ExecutorService.submit() 返回的 Future 来获取 Callable 的返回值或超时 TimeoutTask 是否会更好。例如

            Future<?> futureTask = executor.submit(new TimeoutTask()); // Run the FutureTask
            try {
                result = futureTask.get(timeOut, TimeUnit.MILLISECONDS); // Check if FutureTask completed in the given time
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                futureTask.cancel(true);
                result = true;  // Return True only when timed out
            } finally {
                executor.shutdownNow(); // Stop the executor
            }
            return result;

我正在使用JDK7。

4

3 回答 3

0

如果您查看 的代码futureTask.cancel,您会发现它只是试图中断正在执行任务的线程。如果任务规则检查中断标志,显式或隐式(通过调用 sleep() 或 wait()),此中断可能会起作用。在 Java 中,没有其他安全的方法可以停止方法的执行。

因此,您可以实现相同的功能,而无需每次都创建单独的单线程执行程序。相反,从waitForProcessToBeCompleted方法中执行 TimerTask。为了收到超时通知,请将监视任务提交给 SheduledExecutorService。监视任务应该中断执行 TimerTask 的线程。如果任务在超时之前完成,则取消正在观看的任务。

这样,您需要一个 SheduledExecutorService,但它消耗的处理器周期非常少,并且可以在整个应用程序中重用。

于 2013-04-16T10:55:05.770 回答
0

我更喜欢使用CountDownLatch

List<List<String>> elements = MyPartition.partition(bigObjectList, size); 
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newSingleThreadExecutor();
CountDownLatch doneSignal =  new CountDownLatch(10);
for(List<String> l: elements) {         
   ReadTask worker = new ReadTask(doneSignal, l);
   tasks.add(executor.submit(worker));
}   

long timeout = 10000;
doneSignal.await(timeout, TimeUnit.SECONDS);
boolean notFinished = false;
if(doneSignal.getCount() > 0) {
  for(Future<?> fut : tasks) {
    if(!fut.isDone()) {
      System.out.println("Sub Thread " + fut + " has not finshed!");
      fut.cancel(true);             
      notFinished = true;
    }
  }
}
于 2013-04-16T10:43:12.760 回答
0

ExecutorService 上的invokeAll方法可用于自动取消超过超时的任务。这使您可以在不关闭线程池的情况下取消任务(如果您愿意,可以将相同的线程池重新用于其他事情)。

private boolean waitForProcessToBeCompleted(long timeOut) {
  ExecutorService executor = Executors.newSingleThreadExecutor();
  List<FutureTask> tasks = new ArrayList<>();
  tasks.add(new SomeFutureTaskThing()));
  List<Future<Boolean>> results;
  try {
    results = executor.invokeAll(tasks, timeOut, TimeUnit.SECONDS);
  } catch (InterruptedException e) {
    Thread.currentThread().interrupt(); // Restore interrupt status.
    return null;
  } catch (ExecutionException e) {
    throw new RuntimeException(e.getCause());
  }
  Future<Boolean> result = results.get(0);
  try {
    return result.get();
  } catch (CancellationException e) {
    System.err.println("Timed out");
    return null;
  }
}
于 2015-06-05T16:10:36.313 回答