4

Iterable<X>多数の要素を持つ不変のものがあります。(たまたまですが、List<>気にしないでください。)

私がやりたいことは、いくつかの並列/非同期タスクを開始しIterable<> て、同じ反復子で反復処理することです。どのインターフェイスを使用すればよいか考えています

to-be-determined インターフェイスを使用した実装例を次に示します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 */
}

これが私の問題です:

  • hasNext() と next() には同期の問題があるため、直接使用しても意味がありませんIterator。hasNext() は、誰かが next() を呼び出す前に呼び出すと役に立ちません。

  • を使いたいのですQueueが、必要な唯一の方法はpoll()

  • ConcurrentLinkedQueue を使用して多数の要素を保持したいのですが、要素を複数回反復処理する必要がある場合を除き、それを使用することはできません。

助言がありますか?

4

2 に答える 2

1

メソッドまたは同等Producerのものを使用して独自のインターフェイスを作成します(たとえば Guava の)。実装オプションは多数ありますが、不変のランダム アクセス リストがある場合は、単純にスレッド セーフなモノトニック カウンター (たとえば AtomicInteger) を維持し、list.get(int) を呼び出すことができます。poll()Supplier

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());
  }
}

これはスレッドセーフですが、使い果たされたときに Option スタイルのものまたは null を返したいと思うでしょう。

于 2011-05-05T23:58:35.873 に答える
0

Iterable を反復処理し、要素に対して作業を実行する複数のワーカー スレッドに要素をディスパッチする 1 つのディスパッチャ スレッドを用意します。ThreadPoolExecutorこれを自動化するために使用できます。

于 2011-05-05T19:43:21.743 に答える