【发布时间】:2018-10-26 02:08:21
【问题描述】:
我对如何以及何时完成可完成的期货有点苦恼。我已经创建了这个测试用例:
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 方法之后只保留了前两项。
但是,testIterator 方法是出乎意料的。所有CompletableFuture 都已完成,限制仅在之后完成。
如果我从流中删除 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)
【问题讨论】:
-
在 Windows 10 64 位上与
java 9.0.4 (build 9.0.4+11)配合良好 -
是的,我确认它使用
jdk-1.8.0_152给出了不正确的结果 -
@MarkoPacak 感谢您发现这是与 Java 版本相关的。我什至没有想到这一点
标签: java java-stream completable-future spliterator