2012-02-26 54 views
6

我想循环遍历一个Java迭代器,但是遇到了麻烦,最好的方法来做到这一点。Java迭代器并发性

这里是我所处的地方,我不会同时做任何事情。

Long l;  
Iterator<Long> i = getUserIDs(); 

while (i.hasNext()) { 
    l = i.next(); 

    someObject.doSomething(l); 
    anotheObject.doSomething(l); 
} 

应该有我做对非迭代器对象的事物之间没有竞争条件,所以我并不担心这一点。我只想加快循环迭代器所需的时间,而不是按顺序循环。

在此先感谢。

回答

4

一个解决方案是使用执行程序来平行工作。

简单的例子:

ExecutorService executor = Executors.newCachedThreadPool(); 

Iterator<Long> i = getUserIDs(); 
while (i.hasNext()) { 
    final Long l = i.next(); 

    Runnable task = new Runnable() { 
     public void run() { 
      someObject.doSomething(l); 
      anotheObject.doSomething(l); 
     } 
    } 

    executor.submit(task); 
} 

executor.shutdown(); 

这将为在迭代的每个项目,然后就做好了一个新的线程。可以通过在Executors类上使用不同的方法来调整使用多少个线程,或者按照您认为合适的方式细分工作(例如,针对每个方法调用使用不同的Runnable)。

5

A可以提供两种可能的方法:

  • 使用一个线程池和调度从收到的迭代器一组处理线程的项目。这不会加速迭代器操作本身,因为这些操作仍然会在单个线程中发生,但它会并行处理实际的处理。

  • 根据如何创建迭代,则可能能够分裂迭代过程以多个片段,每一个都被通过一个单独的线程经由不同Iterator对象处理。例如,查看List.sublist(int fromIndex, int toIndex)List.listIterator(int index)方法。

    这将允许迭代器操作并行发生,但并不总是可以像这样对迭代进行分割,这通常是由于简单的事实,即要迭代的项目不能立即可用。作为一项额外技巧,如果迭代操作昂贵或缓慢(例如访问数据库所需的迭代操作),如果将它们分离到单独的线程(使用迭代器填充),则可能会看到吞吐量改进在BlockingQueue。调度程序线程将只需访问队列,而不必等待迭代器对象检索下一个项目。

在这种情况下,最重要的建议是:“用你的仿形”,通常应遵循“不要过早优化”。通过使用探查器,如VisualVM,您应该能够确定任何性能问题的原因,而不用在黑暗中拍摄。

1

如果您使用的是Java 7,则可以使用新的fork/join;请参阅tutorial

它不仅自动分割线程间的任务,而且如果某个线程早于其他线程完成其任务,它将“窃取”来自其他线程的某些任务。