ForkJoinPool 模拟并发优化求和操作
这里采用的求和算法是 O(n)的复杂度。并且限制了fork()创建新任务的次数最大为核心线程数、
但是通过二分来划分fork的创建,会让一部分线程处于等待状态。 是不如均匀的分成 核心线程数等份任务的。
package mypractice;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j(topic = "c.Main")
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Runtime.getRuntime().availableProcessors() : " + Runtime.getRuntime().availableProcessors());
ForkJoinPool forkJoinPool = new ForkJoinPool();
long a = 1, b = 3_000_000_000L;
// fork
long start = System.currentTimeMillis();
long ret = forkJoinPool.invoke(new MyTask(a, b));
long end = System.currentTimeMillis();
System.out.println("fork执行用时:" + (end - start) + "ms");
System.out.println("ret : " + ret);
// normal
start = System.currentTimeMillis();
long sum = sum(a, b);
end = System.currentTimeMillis();
System.out.println("normal执行用时:" + (end - start) + "ms");
System.out.println("sum : " + sum);
}
static long sum(long a, long b) {
long ret = 0;
for (long i = a; i <= b; i++) {
ret += i;
}
return ret;
}
}
class MyTask extends RecursiveTask<Long>{
private long l, r;
static AtomicInteger ts = new AtomicInteger();
public MyTask(long l, long r) {
this.l = l;
this.r = r;
}
@Override
protected Long compute() {
long mid = l + (r - l) / 2, ret = 0;
if(l == r) {
return mid;
}
if(l > r)
return 0L;
int h;
while((h = ts.get()) < Runtime.getRuntime().availableProcessors()) {
if (ts.compareAndSet(h, h + 2)) {
MyTask lTask = new MyTask(l, mid), rTask = new MyTask(mid + 1, r);
lTask.fork();
rTask.fork();
System.out.println("h : " + h);
return lTask.join() + rTask.join();
}
}
return Main.sum(l, r);
}
}
执行结果:
可以看出效率提升很明显