17

私は大量のデータを持っており、遅いがクリーンなメソッドを呼び出し、最初のメソッドの結果に副作用のある高速メソッドを呼び出したいと考えています。私は中間結果には興味がないので、それらを収集しないようにしたいと思います。

明らかな解決策は、並列ストリームを作成し、遅い呼び出しを行い、ストリームを再び順次にし、高速呼び出しを行うことです。問題は、すべてのコードがシングル スレッドで実行され、実際の並列処理がないことです。

コード例:

@Test
public void testParallelStream() throws ExecutionException, InterruptedException
{
    ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors() * 2);
    Set<String> threads = forkJoinPool.submit(()-> new Random().ints(100).boxed()
            .parallel()
            .map(this::slowOperation)
            .sequential()
            .map(Function.identity())//some fast operation, but must be in single thread
            .collect(Collectors.toSet())
    ).get();
    System.out.println(threads);
    Assert.assertEquals(Runtime.getRuntime().availableProcessors() * 2, threads.size());
}

private String slowOperation(int value)
{
    try
    {
        Thread.sleep(100);
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
    return Thread.currentThread().getName();
}

を削除するsequentialと、コードは期待どおりに実行されますが、明らかに、複数のスレッドで非並列操作が呼び出されます。

そのような動作に関する参考文献や、一時的なコレクションを回避する方法をお勧めできますか?

4

2 に答える 2

2

現在の実装では、Stream はすべて並列またはすべて順次のいずれかです。Javadocはこれについて明示しておらず、将来変更される可能性がありますが、これは可能であると述べています。

S パラレル()

同等の並列ストリームを返します。ストリームが既に並列であったか、基になるストリームの状態が並列になるように変更されたために、それ自体が返される場合があります。

関数をシングル スレッドにする必要がある場合は、ロックまたは同期ブロック/メソッドを使用することをお勧めします。

于 2016-03-02T09:41:56.783 に答える