(手机横屏看源码更方便)
注:java源码分析部分如无特殊说明均基于 java8 版本。
注:本文基于ForkJoinPool分治线程池类。
简介
随着在硬件上多核处理器的发展和广泛使用,并发编程成为程序员必须掌握的一门技术,在面试中也经常考查面试者并发相关的知识。
今天,我们就来看一道面试题:
如何充分利用多核CPU,计算很大数组中所有整数的和?
剖析
单线程相加?
我们最容易想到就是单线程相加,一个for循环搞定。
线程池相加?
如果进一步优化,我们会自然而然地想到使用线程池来分段相加,最后再把每个段的结果相加。
其它?
Yes,就是我们今天的主角——ForkJoinPool,但是它要怎么实现呢?似乎没怎么用过哈^^
三种实现
OK,剖析完了,我们直接来看三种实现,不墨迹,直接上菜。
/**
* 计算1亿个整数的和
*/
public class ForkJoinPoolTest01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 构造数据
int length = 100000000;
long[] arr = new long[length];
for (int i = 0; i < length; i++) {
arr[i] = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
}
// 单线程
singleThreadSum(arr);
// ThreadPoolExecutor线程池
multiThreadSum(arr);
// ForkJoinPool线程池
forkJoinSum(arr);
}
private static void singleThreadSum(long[] arr) {
long start = System.currentTimeMillis();
long sum = 0;
for (int i = 0; i < arr.length; i++) {
// 模拟耗时,本文由公从号“彤哥读源码”原创
sum += (arr[i]/3*3/3*3/3*3/3*3/3*3);
}
System.out.println("sum: " + sum);
System.out.println("single thread elapse: " + (System.currentTimeMillis() - start));
}
private static void multiThreadSum(long[] arr) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
int count = 8;
ExecutorService threadPool = Executors.newFixedThreadPool(count);
List> list = new ArrayList<>();
for (int i = 0; i < count; i++) {
int num = i;
// 分段提交任务
Future future = threadPool.submit(() -> {