使用多线程从List获取对象

时间:2015-09-28 16:39:54

标签: java multithreading performance

我有一个包含100,000个对象的列表。想要尽快阅读列表。

将它们分成多个小型列表,每个500个对象

    List<List<String>> smallerLists = Lists.partition(bigList, 500);

    ExecutorService executor = Executors.newFixedThreadPool(smallerLists.size());

    for(int i = 0; i < smallerLists.size();i++) {   
        MyXMLConverter xmlList = new MyXMLConverter(smallerLists.get(i));
        executor.execute(xmlList);
    }
    executor.shutdown();
    while (!executor.isTerminated()) {}

MyXMLConverter.java 再次使用50个线程的Executors来处理这500个对象List。

public MyXMLConverter(List<String> data){
  this.data = data;
}

@Override
public void run() {
    try {
        convertLine();
    } catch (Exception ex) {}
}

public void convertLine(){
  ExecutorService executor = Executors.newFixedThreadPool(50);
  for(int i = 0; i < data.size();i++) {
     MyConverter worker = new MyConverter(list.get(i));
     executor.execute(worker);
  }
  executor.shutdown();
  while (!executor.isTerminated()) {}

}

从List中获取对象耗费了大量时间。有没有更好的方法来做到这一点?请建议。

2 个答案:

答案 0 :(得分:2)

由于每个项目的处理时间可能会有所不同,因此最好让每个工作线程直接从主列表中将下一个项目拉入进程,以便最后保持所有线程忙碌。

从共享列表中提取多线程最好使用其中一个并发集合。在您的情况下,ConcurrentLinkedQueue将成为主要候选人。

因此,将列表复制到ConcurrentLinkedQueue(或直接构建&#34;列表&#34;作为队列),让线程调用poll()直到它返回null }。

如果构建100000个元素的列表也需要时间,您甚至可以通过允许工作线程在构建队列时开始工作来启动该过程。为此,您使用LinkedBlockingQueue,工作人员会拨打take()

然后你会在队列中添加一个特殊元素来标记结束,当一个worker得到结束标记时,它会把它放回到下一个worker的队列中,然后退出。

答案 1 :(得分:1)

有两个主要问题

  • 您的代码创建了200 * 50 + 50个帖子
  • 他们中的大多数人无限循环:while (!executor.isTerminated()) {}

我建议使用这样的东西。

    ExecutorService executor = Executors.newFixedThreadPool(COUNT_OF_YOUR_PROCESSOR_CORESS * 2);

    List<Future<?>> futureList = new ArrayList<Future<?>>();

    for(String currentString : bigList) {
        MyConverter worker = new MyConverter(currentString);
        Future<?> future = executor.submit(worker);
        futureList.add(future);
    }

    Collections.reverse(futureList);
    for (Future<?> future : futureList){
        future.get();
    }

    executor.shutdown(); //No worries. All task already executed here

或者如果你是Java 8上瘾那么

bigList.parallelStream().forEach(s -> new MyConverter(s).run());