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

2022-09-02 20:57:39

我使用执行器提交了一个任务,我需要它在一段时间后停止(例如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       
         }
   }

但是我总是得到一个错误:我有一个共享的Vector,需要由任务修改,然后由线程读取,即使我停止所有任务,如果超时发生,我得到:

Exception in thread "Thread-1" java.util.ConcurrentModificationException

有什么问题吗?如何停止提交的 5 分钟后仍在工作的任务?


答案 1

仅仅因为您调用并不意味着任务将自动停止。您必须在任务中执行一些工作以确保它将停止:cancel()Future

  • 使用,以便将中断发送到任务。cancel(true)
  • 处理。如果任务中的函数抛出 ,请确保在捕获异常时尽快优雅地退出。InterruptedExceptionInterruptedException
  • 定期检查任务是否执行连续计算。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;
    } 
}

此外,正如其他文章所提到的:即使使用线程安全类也可以抛出,因为您从中获取的迭代器不是线程安全的,因此需要同步。增强的 for 循环使用迭代器,因此请注意:ConcurrentModificationExceptionVectorVector

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

答案 2

来自您的调用到,而您的执行者正在迭代您的 .您可以尝试执行的操作是在 ExecutorService 上调用 shutdownNow()ConcurrentModificationExceptiontasks.clear()tasksVector