3

私は、完了可能な先物がいつどのように完成するかについて少し苦労しています。このテスト ケースを作成しました。

import org.junit.Test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class StreamOfCompletableFuturesTest {
    @Test
    public void testList() {
        completeFirstTwoElements(
                Stream.of("list one", "list two", "list three", "list four", "list five")
        );
    }

    @Test
    public void testIterator() {
        Iterator<String> iterator = Arrays.asList("iterator one", "iterator two", "iterator three", "iterator four", "iterator five").iterator();

        completeFirstTwoElements(
            StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
        );
    }

    private void completeFirstTwoElements(Stream<String> stream) {
        stream
                .map(this::cf)
                .limit(2)
                .parallel()
                .forEach(cf -> {
                    try {
                        System.out.println(cf.get());
                    } catch (InterruptedException | ExecutionException e) {
                        throw new RuntimeException(e);
                    }
                });
    }

    private CompletableFuture<String> cf(String result) {
        return CompletableFuture.supplyAsync(() -> {
            System.out.println("Running " + result);
            return result;
        });
    }
}

出力は次のとおりです。

Running list one
Running list two
list two
list one
Running iterator one
Running iterator two
Running iterator three
Running iterator four
Running iterator five
iterator two
iterator one

testListメソッドは期待どおりに機能します。はCompletableFuture最後にのみ評価されるため、 limit メソッドの後は最初の 2 つの項目のみが保持されます。

しかし、そのtestIterator方法は予想外です。すべてCompletableFutureの 's が完了し、制限が行われるのは後でのみです。

parallel()ストリームからメソッドを削除すると、期待どおりに機能します。ただし、forEach()私の完全なプログラムでは長時間実行されるメソッドであるため、処理 ( ) は並行して実行する必要があります。

なぜこれが起こっているのか説明できる人はいますか?

これは Java のバージョンに依存しているように見えるので、私は 1.8 を使用しています。

$ java -version
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
4

2 に答える 2