Java 使用ExecutorService的超时任务

Java 使用ExecutorService的超时任务,java,concurrency,Java,Concurrency,我已经使用ExecutorService实现了超时任务。在下面的方法中,我正在提交超时任务,如果它在给定的时间内超时,我将取消该任务并关闭执行器 private boolean waitForProcessToBeCompleted(long timeOut) { boolean result = false; ExecutorService executor = Executors.newSingleThreadExecutor();

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

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;
        }
private boolean waitForProcessToBeCompleted(长超时){
布尔结果=假;
ExecutorService executor=Executors.newSingleThreadExecutor();
//创建将要运行的FutureTask
FutureTask FutureTask=新建FutureTask(新建超时任务());
executor.submit(futureTask);//运行futureTask
试一试{
结果=futureTask.get(超时,时间单位为毫秒);//检查futureTask是否在给定时间内完成
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
e、 printStackTrace();
}捕获(超时异常e){
futureTask.cancel(true);
result=true;//仅在超时时返回true
}最后{
executor.shutdownow();//停止执行器
}
返回结果;
}
它运行得很好,我没有任何问题

然而,我想知道这是否是最好的代码设计。我只是想知道使用ExecutorService.submit()返回的Future来获取可调用的返回值或超时任务是否更好。e、 g

            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;
Future-futureTask=executor.submit(new TimeoutTask());//运行未来任务
试一试{
结果=futureTask.get(超时,时间单位为毫秒);//检查futureTask是否在给定时间内完成
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
e、 printStackTrace();
}捕获(超时异常e){
futureTask.cancel(true);
result=true;//仅在超时时返回true
}最后{
executor.shutdownow();//停止执行器
}
返回结果;

我正在使用JDK7。

我更喜欢使用
倒计时锁存器

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;
    }
  }
}
List elements=MyPartition.partition(bigObjectList,size);
列表>();
ExecutorService executor=Executors.newSingleThreadExecutor();
CountDownLatch doneSignal=新的CountDownLatch(10);
对于(列表l:元素){
ReadTask worker=新的ReadTask(doneSignal,l);
任务。添加(执行者。提交(工作者));
}   
长超时=10000;
doneSignal.wait(超时,时间单位为秒);
布尔notFinished=false;
if(doneSignal.getCount()>0){
for(未来未来未来:任务){
如果(!fut.isDone()){
System.out.println(“子线程”+fut+“尚未找到!”);
未来取消(真);
notFinished=真;
}
}
}

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

因此,您可以实现相同的功能,而无需每次创建单独的单线程执行器。相反,从
waitForProcessToBeCompleted
方法中执行TimerTask。要获得超时通知,请将监视任务提交给ScheduledExecutorService。监视任务应该中断执行TimerTask的线程。如果任务在超时之前完成,请取消监视任务

这样,您需要一个ScheduledExecutorService,但它只消耗很少的处理器周期,可以在整个应用程序中重用。

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

private boolean waitForProcessToBeCompleted(长超时){
ExecutorService executor=Executors.newSingleThreadExecutor();
列表任务=新建ArrayList();
添加(newsomefuturetaskshing());
列出结果;
试一试{
结果=executor.invokeAll(任务、超时、时间单位.秒);
}捕捉(中断异常e){
Thread.currentThread().interrupt();//恢复中断状态。
返回null;
}捕获(执行例外){
抛出新的RuntimeException(例如getCause());
}
未来结果=结果。获取(0);
试一试{
返回result.get();
}捕获(取消异常e){
System.err.println(“超时”);
返回null;
}
}

谢谢阿列克谢。但是,在上面的代码设计中,我可以使用submit()返回的Future()来获得()结果,而不是使用单独的FutureTask。这有意义吗?它没有意义,因为提交(可调用)返回的未来实际上是一个未来任务。下面是两种方法,再次感谢。但我只是想知道是否使用submit()返回的Future对象,我不需要显式声明它。我只是使用返回值。无论如何,谢谢。
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;
  }
}