Java执行者:如何停止提交的任务?

Java执行者:如何停止提交的任务?,java,multithreading,executorservice,Java,Multithreading,Executorservice,我已使用executors提交了一个任务,需要在一段时间后(例如5分钟)停止该任务。我试过这样做: for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) { try { fut.get(); } catch (CancellationException ex) { fut.cancel(true);

我已使用executors提交了一个任务,需要在一段时间后(例如5分钟)停止该任务。我试过这样做:

   for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) {
         try {
             fut.get(); 
         } catch (CancellationException ex) {
             fut.cancel(true);   
             tasks.clear();
         } catch(ExecutionException ex){
             ex.printStackTrace(); //FIXME: gestita con printstack       
         }
   }

有什么不对劲吗?如何停止5分钟后仍在工作的已提交任务

ConcurrentModificationException最常见的情况是
向量在迭代的同时被修改。通常,这将在单个线程中完成。您需要在整个迭代过程中锁定
向量
(注意不要死锁)。

ConcurrentModificationException
来自您对
任务的调用。clear()
,而您的异常者正在迭代您的
任务
向量
。您可以尝试调用ExecutorService,这并不意味着任务将自动停止。您必须在任务中执行一些工作,以确保任务将停止:

  • 使用
    cancel(true)
    以便向任务发送中断
  • 句柄
    中断异常
    。如果任务中的某个函数抛出一个
    中断异常
    ,请确保捕获异常后尽快优雅地退出
  • 如果任务执行连续计算,则定期检查
    Thread.currentThread().isInterrupted()
例如:

class LongTask implements Callable<Double> {
    public Double call() {
        
         // Sleep for a while; handle InterruptedException appropriately
         try {
             Thread.sleep(10000);
         } catch (InterruptedException ex) {
             System.out.println("Exiting gracefully!");
             return null;
         }


         // Compute for a while; check Thread.isInterrupted() periodically
         double sum = 0.0;
         for (long i = 0; i < 10000000; i++) {
             sum += 10.0
             if (Thread.currentThread().isInterrupted()) {
                 System.out.println("Exiting gracefully");
                 return null;
             }
         }

         return sum;
    } 
}
get()是一个阻塞调用,即使在超时之后,您也会阻塞,直到任务完成。如果您想在尽可能接近5分钟标记时停止,您确实需要检查中断标志,我建议您使用Thread.isInterrupted()方法来执行此操作,该方法保留中断状态。如果您想立即停止并且不需要清除任何状态,那么抛出一个异常,该异常将被将来捕获并作为ExecutionException指示给您

fut.cancel(true)不做任何事情,因为invokeAll()方法已经为您完成了这项工作

除非在其他地方使用“tasks”集合,否则可能不需要对其调用clear()。这不会成为问题的根源,因为在调用clear()时,invokeAll()方法已经完成了对列表的处理。但是,如果您需要开始形成一个要执行的新任务列表,我建议您形成一个新任务列表,而不是使用旧的新任务列表


不幸的是,我对你的问题没有答案。我在这里没有看到足够的信息来诊断它。您提供的代码片段中没有任何内容表明库类/方法的使用不当(只是不必要)。如果您包含完整的堆栈跟踪,而不是一行错误,则可能会出现这种情况。

fut.cancel(true)放入在finally块中

是的,我知道引发异常的原因,但不应该。迭代是在我发布的部分代码之后进行的,因此,如果代码运行良好,我不应该出现异常…@Raffaele Di Fazio:我已经格式化了代码-并添加了一个右括号,请检查其准确性。谢谢,我很抱歉格式化错误。非常好-不知何故我从未遇到线程。interrupted()-我明天可以使用它!首先,调用future.cancel(true)完全不起任何作用。invokeAll的契约声明它将在返回之前取消任务,并且实现使用最后一个块来确保它。第二,永远不要调用Thread.interrupted(),这样做会清除线程的中断状态。大多数实现都希望使用Thread.isInterrupted()。清除旗帜应该受到仔细检查。第三,他不必处理InterruptedException,除非他使用诸如锁获取之类的阻塞方法,然后编译器确保他是。FutureTask将捕获异常。@Tim Bender:你说得对:future.cancel(true)什么都不做,由我自己测试。但是我还不明白你认为我应该做什么。@Tim Bender:你对Thread.interrupted()和Thread.isInterrupted()的看法绝对正确。实际语法是Thread.currentThread().isInterrupted()。@Tim Bender:您不必捕获InterruptedException,但是如果您想在方法退出之前处理清理,您可能需要捕获并重试。我在其他地方使用了该集合,它在while循环中,因此,当循环重复时,它需要被清除才能为空。当然,我可以在文章中显示的代码之后执行clear(),这应该可以。我的问题的重要部分不是例外:我需要知道的是如何在5分钟后阻止未来,当然,我会按照你的建议尝试抛出一个例外。我甚至可以改变提交任务的方式。我在这里学到了这一点:
class LongTask implements Callable<Double> {
    public Double call() {
        
         // Sleep for a while; handle InterruptedException appropriately
         try {
             Thread.sleep(10000);
         } catch (InterruptedException ex) {
             System.out.println("Exiting gracefully!");
             return null;
         }


         // Compute for a while; check Thread.isInterrupted() periodically
         double sum = 0.0;
         for (long i = 0; i < 10000000; i++) {
             sum += 10.0
             if (Thread.currentThread().isInterrupted()) {
                 System.out.println("Exiting gracefully");
                 return null;
             }
         }

         return sum;
    } 
}
final Vector<Double> vector = new Vector<Double>();
vector.add(1.0);
vector.add(2.0);

// Not thread safe!  If another thread modifies "vector" during the loop, then
// a ConcurrentModificationException will be thrown.
for (Double num : vector) {
    System.out.println(num);
}

// You can try this as a quick fix, but it might not be what you want:
synchronized (vector) {    // "vector" must be final
    for (Double num : vector) {
        System.out.println(num);
    }
}