Java 执行器服务和列表<;未来<;可调用>&燃气轮机;带有ConcurrentModificationException

Java 执行器服务和列表<;未来<;可调用>&燃气轮机;带有ConcurrentModificationException,java,concurrency,Java,Concurrency,我有一个ExecutorService,它返回一个定义为List callables=Collections.synchronizedList(new ArrayList())的列表 当我第一次遇到这个问题时,我把它做成了一个synchronizedList,因为我认为它是线程安全的,但问题仍然存在 我遇到的问题是以下代码在Future next=I.next()处抛出ConcurrentModificationException如下。值得注意的是,它在轰炸前部分通过了名单

我有一个ExecutorService,它返回一个定义为
List callables=Collections.synchronizedList(new ArrayList())的列表

当我第一次遇到这个问题时,我把它做成了一个synchronizedList,因为我认为它是线程安全的,但问题仍然存在

我遇到的问题是以下代码在Future next=I.next()处抛出ConcurrentModificationException如下。值得注意的是,它在轰炸前部分通过了名单

          ExecutorWorker snapshotExecutorWorker=new ExecutorWorker(this); 
      Iterator<Future<Object>> i= futures.iterator();
      while(i.hasNext()){
        Future<Object> next = i.next();//List<Callable>
        try {
            Object get = next.get();
            Class<? extends Object> aClass = get.getClass();
            System.out.println("Class= "+aClass);
         List<Callable> l=   (List)get;
         System.out.println("L.size= "+l.size());
       for(int a=0;a<l.size();a++){                 
        snapshotExecutorWorker.addTask(l.get(a));
       }

        } catch (InterruptedException ex) {
            Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
        }

      }
ExecutorWorker快照ExecutorWorker=新的ExecutorWorker(此);
迭代器i=futures.Iterator();
while(i.hasNext()){
Future next=i.next();//列表
试一试{
Object get=next.get();
类addTask(可调用的r){
未来价值=ecs.submit(r);
monitor.addFuture(未来值);
System.out.println(“可调用添加在[ExecutorWorker]中”);
增加(未来价值);
monitor.tasksAdded(真);
回归未来价值;
}
/**
*此方法返回一个包含未来结果的列表。请使用Future.get()进行检索。
*@返回
*/
公共列表getResults(){
返回结果;
}
@凌驾
受保护的void done(){
}
@凌驾
受保护列表doInBackground()引发ExecutionException、InterruptedException{
//System.out.println(“执行者:在后台执行”);
//System.out.println(“Jobs.size=“+Jobs.size());
for(int i=0;i
Collections.synchronizedList()只返回已同步方法的列表,而不更新迭代器,因此ConcurrentModificationException仍然是可能的。

如果在迭代列表时修改列表,迭代器将失效,并在下次使用它们时抛出ConcurrentModificationException(可能。请阅读“迭代器的fail-fast属性”(详细信息)

使之成为synchronizedList所做的只是将对list方法的每次调用包装在一个synchronized块中

我相信在您的特定示例中,问题在于addTask导致您正在迭代的列表被修改

这个问题说明了迭代器::remove()的用法,它允许在迭代某些类型的集合时对它们进行一些修改,尽管这与您的实际问题有些相切:

现在没有时间讨论它,但是你从哪里得到你迭代的futures集合?因为你似乎在试图迭代它时正在更改该集合,而这……嗯……你做不到。你的第一个代码块似乎与你的第二个代码块无关。我怀疑第一个代码块是很可能是
addFuture
方法的
Monitor
类,但我不想根据这么多推测来回答。请显示第一个代码块所属的方法和类。您认为切换到for循环可以解决问题吗?这与您使用的循环类型无关。哇,似乎”进入"发送消息:P。问题是,如果迭代器正在迭代的集合被修改,迭代器将变得无效。当您尝试使用以这种方式无效的迭代器时,它将抛出ConcurrentModificationException。要修复您的程序,您需要使它在迭代过程中停止修改列表。一种方法是ach可能是批处理您想要做的修改,然后在循环后立即应用它们。(创建一个“要添加的内容”列表,您的循环将填充该列表,然后您将所有这些内容添加到循环后的实际列表中。例如)
public class ExecutorWorker extends SwingWorker<List<Future>, Object>   implements ExecutorInterface {

List<Future> results = new ArrayList();
ExecutorService executorService = Executors.newFixedThreadPool(100);
ExecutorCompletionService<Object> ecs = new ExecutorCompletionService<>(executorService);
List<Future<Object>> jobs = new ArrayList();
ProgressMonitor progressMonitor;
boolean isExecuting = true;
Monitor monitor;

public ExecutorWorker(Monitor f) {
    monitor = f;

}

public void addMonitor(Monitor f) {
    monitor = f;
}

/**
 *This method adds Callables to the Executor.
 * @param r
 * @return 
 */
@Override
public Future<?> addTask(Callable r) {
    Future futureValue = ecs.submit(r);
    monitor.addFuture(futureValue);
    System.out.println("Callable added in [ExecutorWorker]");
    jobs.add(futureValue);
    monitor.tasksAdded(true);
    return futureValue;
}

/**
 *This method returns a List containing the Future results. Use Future.get() to retrieve.
 * @return
 */
public List<Future> getResults() {
    return results;
}

@Override
protected void done() {

}

@Override
protected List<Future> doInBackground() throws ExecutionException, InterruptedException {
//        System.out.println("Executor: In Do In BackGround");
//        System.out.println("Jobs.size= " + jobs.size());

    for (int i = 0; i < this.jobs.size(); i++) {
        Future<Object> take = ecs.take();
        results.add(take);
        monitor.tasksCompleted(true);
        int v = (int) ((monitor.getCompletedTasks() /          this.monitor.getTotalTasks()) * 100);
        this.setProgress(v);
        String message = String.format("Processing " + (i + 1) + " of " +      jobs.size() + " Jobs. %d%%.\n", v);
        System.out.println("Message= " + message);
        progressMonitor.setNote(message);


    }

    return results;

}

public void setProgressMonitor(ProgressMonitor progressMonitor) {
    this.progressMonitor = progressMonitor;
}
}