2011-05-05 59 views
4

我有一個不可變的Iterable<X>與大量的元素。 (這恰好是一個List<>,但從來沒有介意。)java:通過不可變的迭代併發迭代

我想什麼做的是開始的幾個平行/異步任務遍歷Iterable<>用相同的迭代器我想知道什麼接口我應該使用

下面是與待確定的接口QuasiIteratorInterface的實現:

public void process(Iterable<X> iterable) 
{ 
    QuasiIteratorInterface<X> qit = ParallelIteratorWrapper.iterate(iterable); 
    for (int i = 0; i < MAX_PARALLEL_COUNT; ++i) 
    { 
     SomeWorkerClass worker = new SomeWorkerClass(qit); 
     worker.start(); 
    } 
} 

class ParallelIteratorWrapper<T> implements QuasiIteratorInterface<T> 
{ 
    final private Iterator<T> iterator; 
    final private Object lock = new Object(); 
    private ParallelIteratorWrapper(Iterator<T> iterator) { 
     this.iterator = iterator; 
    } 
    static public <T> ParallelIteratorWrapper<T> iterate(Iterable<T> iterable) 
    { 
     return new ParallelIteratorWrapper(iterable.iterator()); 
    } 
    private T getNextItem() 
    { 
     synchronized(lock) 
     { 
     if (this.iterator.hasNext()) 
      return this.iterator.next(); 
     else 
      return null; 
     } 
    } 
    /* QuasiIteratorInterface methods here */ 
} 

這裏是我的問題:

  • 它沒有意義的,直接使用Iterator,因爲hasNext( )和next()有一個同步問題,其中hasNext()在別人調用next()之前無用。

  • 我喜歡使用Queue,但我需要的唯一方法是poll()

  • 我喜歡使用的ConcurrentLinkedQueue牽我的大量元素的......除了我可能通過迭代元素不止一次,所以我不能使用它。

有什麼建議嗎?

+0

在想要對數據進行第二次傳遞的場景中,迭代次序是否需要與第一次傳遞相同? – ChrisH 2011-05-05 19:33:29

+0

除了課程鎖定以及'null'是許多List實現的有效條目之外,問題是什麼? – 2011-05-05 19:35:22

+0

@ChrisH:是的,訂單應該始終相同。 – 2011-05-05 19:36:19

回答

1

使用poll()方法或同等方法(例如Guava的Supplier)創建您自己的Producer接口。實施方案有很多,但如果你有一個不變的隨機訪問列表,那麼你可以簡單地保持一個線程安全的單調計數器(的AtomicInteger例如),並調用list.get(INT),例如:

class ListSupplier<T> implements Supplier<T> { 
    private final AtomicInteger next = new AtomicInteger(); 
    private final List<T> elements; // ctor injected 

    … 
    public <T> get() { 
    // real impl more complicated due to bounds checks 
    // and what to do when exhausted 
    return elements.get(next.getAndIncrement()); 
    } 
} 

也就是說線程-safe,但是你可能想要返回一個Option樣式的東西,或者在耗盡時返回null。

0

有一個調度器線程遍歷Iterable並將元素分派給多個工作線程來執行元素上的工作。您可以使用ThreadPoolExecutor來自動執行此操作。

+0

謝謝,但我不想將控制共享訪問的機制與工作調度機制(這是複雜的,並有一些限制,因爲這個問題的範圍之外的原因)元素。 – 2011-05-05 19:48:19