数据准备:
private static final int COUNT = 100000;
private Vector<String> datas;
@Before
public void init() {
datas = new Vector<>();
for (int i = 0; i < COUNT; i++) {
datas.add("data-" + i);
}
}
使用ParallelStream并行打印
@Test
public void testParallelStream(){
datas.parallelStream().forEach(p->{
System.out.println("p=" + p + "," + Thread.currentThread().getName());
});
}
打印结果
p=data-39215,ForkJoinPool.commonPool-worker-3
p=data-70897,main
p=data-70898,main
p=data-70899,main
p=data-70900,main
p=data-70901,main
p=data-70902,main
p=data-70903,main
p=data-70904,main
p=data-4288,ForkJoinPool.commonPool-worker-1
p=data-4289,ForkJoinPool.commonPool-worker-1
通过打印结果可以其使用了ForJoin的线程进行多线程打印逻辑,并且线程号递增至p=data-688,ForkJoinPool.commonPool-worker-7是由于测试机的CPU核心数就是8
Runtime.getRuntime().availableProcessors()
所以main+上7个ForkJoinPool.commonPool-worker等于CPU的核心数,验证了ParalleStream默认使用的是CPU核心数的线程池大小。
使用CompletableFutrue则需要将数据集自行拆分,进行多线程的处理
@Test
public void testCompletableFuture() {
ExecutorService nodeExecutor = new ThreadPoolExecutor(10, 100, 100L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), UserThreadFactory.build("discovery-l3-node"));
List<List<String>> mePartition = Lists.partition(datas, 20);
List<CompletableFuture<Void>> printFuture = mePartition.stream().map(ids -> CompletableFuture.runAsync(() -> {
ids.forEach(p -> {
System.out.println("p=" + p + "," + Thread.currentThread().getName());
});
}, nodeExecutor)).collect(Collectors.toList());
CompletableFuture.allOf(printFuture.toArray(new CompletableFuture[]{})).join();
}
代码中通过Lists.partition对集合进行了分组,然后利用核心线程数为10的线程进行数据的打印,结果如下:
p=data-196,discovery-l3-node-1-thread-10
p=data-197,discovery-l3-node-1-thread-10
p=data-198,discovery-l3-node-1-thread-10
p=data-199,discovery-l3-node-1-thread-10
p=data-200,discovery-l3-node-1-thread-1
p=data-201,discovery-l3-node-1-thread-1
p=data-202,discovery-l3-node-1-thread-1
上述两种方式的特点很明显
在多个CompletableFuture里如果一个线程安全的集合如vector操作,会导致多个CompletableFuture针对vector实际上是串行
@Test
public void testParallelStream2() throws ExecutionException, InterruptedException {
ForkJoinPool forkJoinPool = new ForkJoinPool(10);
ForkJoinTask<?> submit = forkJoinPool.submit(() -> {
datas.parallelStream().forEach(p -> {
System.out.println("p=" + p + "," + Thread.currentThread().getName());
});
});
submit.get();
}