2012-02-26 76 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

它不僅自動分割線程間的任務,而且如果某個線程早於其他線程完成其任務,它將「竊取」來自其他線程的某些任務。