2016-04-06 4 views
3
class MyItem { 
    private param1, param2, param3; 
} 

MyItem item = new MyItem(); 

computeParam1(item); 
computeParam2(item); 
computeParam3(item); 
waitForAllParamsToBeSet(); 

各ステップは互いに独立しており、各ステップは最終結果としてオブジェクトにパラメタを書き込む。 メソッドはロジックとは全く異なり、再帰はありません。複雑なオブジェクトを作成するためのステップを並列化する方法は?

可能であれば、これらのステップをどのように並列化できますか?

答えて

2

すべてcomputeParamX()は1つのMyItem引数を受け入れると、ボイドリターンを持っているとして、彼らはConsumer<MyItem>の署名を持っています。次のようにだからあなたは、並列ストリームの.forEach()でそれらを呼び出して、その実行を並列化することができます.forEach()として

final MyItem item = new MyItem(); 
Stream.<Consumer<MyItem>>of(this::computeParam1, this::computeParam2, this::computeParam3) 
      .parallel() 
      .forEach(c -> c.accept(item)); 

を端末操作である、それは戻った後、あなたが安全にitemオブジェクトを使用することができますので、それは、すべての操作が完了するまでブロックします。

+0

これで、いくつかのスレッドから 'item'に書き込んでいます。これが安全であることを知るには、 'MyItem'クラスについては十分に分かりません。 – weston

+1

@ westonはい、そうです。これを使う前に、 'computeParamX'メソッドが干渉しないようにする必要があります。 OPは彼らが独立していると言います、そして私は信じない理由を見ません。 –

+0

疑わしい主な理由は、計算が独立していると、計算後に割り当てられるのではなく、なぜインスタンスがそれらに渡されるのかということです。すなわち、なぜそれがなぜではないのですか?item.setParam1(computeParam1()); 'etc? – weston

3

Futuresを開始してから、結果を待ってから割り当ててください。

Future<Type1> item1 = ComputeParam1(); 
Future<Type2> item2 = ComputeParam2(); 
Future<Type3> item2 = ComputeParam3(); 

MyItem item = new MyItem(); 

assignParam1(item1.get()); 
assignParam2(item2.get()); 
assignParam3(item3.get()); 
+1

でタスクを起動します//spring.io/guides/gs/async-method/ – membersound

+0

あなたが受け入れた答えに注意してください – weston

2

のJava 8では、あなたは、単に次のようなタスクのあなたのコレクションを作成することができます。https::

Collection<Runnable> tasks = Arrays.asList(
    () -> System.out.println("Compute param1"), 
    () -> System.out.println("Compute param2"), 
    () -> System.out.println("Compute param3") 
); 

が続いて使用した場合でも、より多くの春便利な機能を、だパラレル

tasks.parallelStream().forEach(Runnable::run); 
+0

この方法では、スレッドプールを指定することはできません(回避策のみ):http://stackoverflow.com/questions/21163108/custom-thread-pool-in-java-8-parallel-stream – user140547

+1

このアプローチでは、Runtime.getRuntime()。availableProcessors()に対応するターゲットマシン上にコアを持つものと同じ数のスレッドを起動するForkJoinPoolを使用しますが、_java.util.concurrentなどのシステムプロパティによってデフォルト値を変更できます。 ForkJoinPool.common.parallelism_詳細はこちらhttps://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html –

+0

はい、しかし、そのスレッドは、すべてのタスクが並列ストリームがデフォルトのForkJoinPoolで実行されています。これは、他のタスクがそのプールを遅くしたり、デッドロックしたりする場合に懸念される可能性があります。 – user140547

関連する問題