1

我正在将 ExecutorService 用于多线程进程 - 我有 ID 列表,对于每个 ID,我使用线程制作代码的一部分。

ExecutorService executor = Executors.newFixedThreadPool(4);   
for (String id : listOfIDs) {
    Runnable worker = new WorkerThread(id);
    executor.execute(worker);
}
executor.shutdown();
....

一切正常,结果符合预期。但是因为我有很多ID,所以我需要更有效地做这部分。我有性能问题,似乎是因为创建了 WorkerThreads 的 lof。我决定为 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 来“批量”运行某些进程?

4

1 回答 1

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

于 2013-07-07T05:05:27.490 回答