2016-06-29 4 views
1

私は 'someObject'でいっぱいのArrayListを持っています。私は4つのスレッド(Futures & Callablesを使って)を使って、このリストを繰り返し処理する必要があります。スレッドは、それが渡る上位5つの値を持つオブジェクトを保持します。最初に並列ストリームを作成しようとしましたが、うまくいきませんでした。私は考えていないいくつかの明白なことは、各スレッドは、おそらく同じオブジェクトを2回つかむことなく、オブジェクトを反復することができますか?Javaで重複しないで単一のリストを並行して反復する

+0

私はこの問題に従っていますが、おそらくオブジェクトを4つのサブリストに分割しています(スレッドごとに1つずつ)。 – Gavin

答えて

1

あなたは、リストを反復するためにAtomicIntegerを使用することができます。

class MyRunnable implements Runnable { 
    final List<SomeObject> list; 
    final AtomicInteger counter; // initialize to 0 

    public void run() { 
     while(true) { 
      int index = counter.getAndIncrement(); 
      if(index < list.size()) { 
       do something with list.get(index); 
      } else { 
       return; 
      } 
     } 
    } 
} 

限り、各MyRunnableが同じAtomicInteger参照を持っているとして、彼らはあなたがAtomicIntegerまたはいずれかを必要としないインデックス

1

を複製しません。その点については他の同期が必要です。

処理スレッドの数に基づいて(その数は前もって知られています)論理的にパーティションを分割し、それぞれが[from、to]のセクションで動作するようにするだけですリスト。

これは常に(安全である限り)常に努力すべきことである(たとえそれがAtomicIntegerのような最適化されたものであっても)同期の必要性を回避します。

擬似コード(リストのコピーを含まない本当にすべての溶液)AtomicIntegerソリューション、このソリューションはまた、あなたがそれを手渡した後、あなたがのリストを変更しないことを前提としてと同様に

class Worker<T> implements Runnable { 
    final List<T> toProcess; 

    protected Worker(List<T> list, int fromInc, int toExcl){ 
     // note this does not allow passing an empty list or specifying an empty work section but you can relax that if you wish 
     // this also implicitly checks the list for null 
     Preconditions.checkArgument(fromInc >= 0 && fromInc < list.size()); 
     Preconditions.checkArgument(toExcl > 0 && fromInc <= list.size()); 
     // note: this does not create a copy, but only a view so it's very cheap 
     toProcess = list.subList(fromInc, toExcl); 
    } 

    @Override 
    public final void run() { 
     for(final T t : toProcess) { 
      process(t); 
     } 
    } 

    protected abstract process(T t); 
} 

各スレッドにオフフックし、処理が開始されました。処理中にリストを変更すると、未定義の動作になります。

関連する問題