4

我有一个Iterable<X>包含大量元素的不可变对象。(它恰好是一个List<>但没关系。)

我想做的是启动一些并行/异步任务来迭代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() 存在同步问题,如果其他人在你之前调用 next(),hasNext() 是无用的。

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

  • 我很想使用 ConcurrentLinkedQueue 来保存我的大量元素......除了我可能不得不多次遍历元素,所以我不能使用它。

有什么建议么?

4

2 回答 2

1

使用方法或等效方法(例如 Guava )创建您自己的Producer接口。实现选项很多,但是如果您有一个不可变的随机访问列表,那么您可以简单地维护一个线程安全的单调计数器(例如 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 并将元素分派到多个工作线程,这些工作线程在元素上执行工作。您可以使用它ThreadPoolExecutor来自动执行此操作。

于 2011-05-05T19:43:21.743 回答