我正在使用ExecutorService进行multiThread进程 - 我有ID列表,对于每个ID,我使用线程编写代码的一部分。
ExecutorService executor = Executors.newFixedThreadPool(4);
for (String id : listOfIDs) {
Runnable worker = new WorkerThread(id);
executor.execute(worker);
}
executor.shutdown();
....
一切正常,结果如预期。但是因为我有很多ID,所以我需要更有效地完成这一部分。我有性能问题,似乎是因为创建lof的WorkerThreads。我决定运行它以获取baseIds列表,稍后在WorkerThread中的 run 方法(或从那里调用的其他方法)循环遍历每个线程的列表。但是我遇到了 java.util.ConcurrentModificationException 的问题。我究竟做错了什么?
for (String id : listOfIDs) {
listForThreads.add(id);
if (listForThreads.size() >= 100) {
Runnable worker = new WorkerThread(listForThreads);
executor.execute(worker);
listForThreads.clear();
}
}
....
public static class WorkerThread implements Runnable {
private List<String> listForThreads;
public WorkerThread (List<String> listForThreads) {
this.listForThreads = listForThreads;
}
public void run() {
for (String id : listForThreads) {
process(id);
}
} ....
我原以为我只会在一个线程中处理更多ID而不是每个线程的id。是否可以使用ExecutorService在'批次'中运行某些进程?
答案 0 :(得分:0)
本节中的代码错误
for (String id : listOfIDs) {
listForThreads.add(id);
if (listForThreads.size() >= 100) {
Runnable worker = new WorkerThread(listForThreads);
executor.execute(worker);
listForThreads.clear();
}
}
迭代列表时不应进行修改。在这里,您将与工作线程共享相同的列表实例。这是在同一个列表实例上进行迭代,并且您正在主线程中同时(同时)清除列表。理想情况下只要与仅执行只读操作的其他线程共享,就应创建ArrayList 的副本。 使用** listForThreads.toArray(new String [listForThreads.size()])创建ArrayList的副本** 或者通过克隆给定列表,请参阅此问题的答案Java ArrayList copy