如何高效的计算1~1000000000之和
程序员文章站
2022-07-10 19:13:15
简单的来算,我们可以采用 for while 之类循环来计算,下面采用的for循环 static void forSum(){ long start = System.currentTimeMillis(); long sum = 0; for (long i = 0; i <= 10_0000_0000; i++) { sum+=i; } long end = System.currentT...
简单的来算,我们可以采用 for while 之类循环来计算,下面采用的for循环
static void forSum(){
long start = System.currentTimeMillis();
long sum = 0;
for (long i = 0; i <= 10_0000_0000; i++) {
sum+=i;
}
long end = System.currentTimeMillis();
System.out.println("for求和="+sum+",所花时间为:"+(end-start));
}
我们可以想想怎么才能更有效率,for是单个线程也即是主线程在执行计算,如果多个线程同时执行计算呢?速度会不会快些,试试
static void poolSum(){
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
ForkJoinTask<Long> submit = forkJoinPool.submit(new SumTask(0L, 10_0000_0000L));
try {
long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("ForkJoinPool求和="+sum+",所花时间为:"+(end-start));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
static class SumTask extends RecursiveTask<Long> {
private static final int THRESHOLD = 50_0000;//阈值
long start;
long end;
public SumTask(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long sum = 0;
//当end与start之间的差小于threshold时,开始进行实际的累加
if (end - start < THRESHOLD) {
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else {//当end与start之间的差大于threshold,即要累加的数超过threshold个的时候,将大任务分解成小任务
long middle = (start + end) / 2;
SumTask left = new SumTask(start, middle);
SumTask right = new SumTask(middle+1, end);
//并行执行两个小任务
left.fork();
right.fork();
//把两个小任务累加的结果合并起来
return left.join() + right.join();
}
}
}
既然多个线程可以,那么多个流并行计算,是不是也可以呢?
static void streamSum(){
long start = System.currentTimeMillis();
long sum = LongStream.rangeClosed(0, 10_0000_0000).parallel().reduce(0,Long::sum);
long end = System.currentTimeMillis();
System.out.println("streamSum求和="+sum+",所花时间为:"+(end-start));
}
运行试试,看看执行的效率怎样?
我们发现好像使用并行流要快一些,其次是多线程,最后是单个线程,那么一定是这样的吗?不急,往下看
我把 THRESHOLD = 50_0000;改动了一下,如下:
static class SumTask extends RecursiveTask<Long> {
private static final int THRESHOLD = 500;//阈值
在运行试试:
发现多线程计算时间变长了,其实这个和阈值有关,我们可以这样想,一个线程池的线程数是不是有限的,我们一直递归下去,不断创建线程,当多出了池子里的线程数,执行的时候就会有线程在等待的,而且,这还和 ForkJoinPool 的工作特点(工作窃取)有关。比如一个工作队列在执行任务,还剩最后一个任务,此时其他的线程来抢任务,就会出现短暂的等待状态。
有兴趣的小伙伴可以去了解一下
本文地址:https://blog.csdn.net/qq_42224683/article/details/107405623
推荐阅读
-
1、计算1000以内所有不能被7整除的整数之和
-
原码,反码,补码详解及如何计算二进制数中1的数量
-
如何高效的计算1~1000000000之和
-
Excel长方形单元格区域中的左上角到右下角的对角线之和如何计算
-
实训:用while循环计算1到20的阶乘之和
-
[原创] 连载 1 - 深入讨论 Android 关于高效显示图片的问题 - 如何高效的加载大位图
-
c语言计算1~n的阶乘之和
-
如何使用java中的for循环语句计算1~100的累加和
-
1002 写出这个数 (20)(20 分) 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10^10
-
python如何计算1到100的和