1、使用Fork/join
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/**
* @author ZFX
* @date2019/3/31 15:09.
*/
public class CountTask extends RecursiveTask<Long> {
/**
* 阀值
*/
static final int THRESHOLD = 10000;
long start;
long end;
public CountTask(long start, long end) {
this.start = start;
this.end = end;
}
/**
* 有返回值的
* @return
*/
@Override
protected Long compute() {
long sum = 0;
// 当阀值小于10000则不分解了
boolean canCompute = (end - start) < THRESHOLD;
if (canCompute) {
for (long i = start; i <= end; i++) {
sum += i;
}
} else {
// 2000
long step = (start + end) / 100;
ArrayList<CountTask> subTasks = new ArrayList<>();
long pos = start;
for (int i = 0; i < 100; i++) {
long lastOne = pos + step;
if (lastOne > end) {
lastOne = end;
}
//0-2000 个计算任务 * 100
CountTask subTask = new CountTask(pos, lastOne);
pos += step + 1;
subTasks.add(subTask);
subTask.fork();// fork
}
for (CountTask t : subTasks) {
sum += t.join();
}
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
CountTask task = new CountTask(0, 200000L);
// 将一个大的任务提交到池中
ForkJoinTask<Long> result = forkJoinPool.submit(task);
long res = 0;
try {
// 等待运算结果
res = result.get();
System.out.println("sum = " + res);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
fork/join使用工作窃取算法、其流程图为
采用双端计算机制,充分利用线程进行并行计算。
2、根据核心线程数计算
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* @author ZFX
* @date2019/3/28 16:52.
*/
public class ConcurrentCalculator {
private ExecutorService exec;
//这个地方,纯粹是“一厢情愿”,“并行执行”不受咱们控制,取决于操作系统的“态度”
private int cpuCoreNumber;
private List<Future<Long>> tasks = new ArrayList<Future<Long>>();
class SumCalculator implements Callable<Long> {
private int[] numbers;
private int start;
private int end;
public SumCalculator(final int[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
public Long call() throws Exception {
Long sum = 0L;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
}
public ConcurrentCalculator() {
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
exec = Executors.newFixedThreadPool(cpuCoreNumber);
}
public Long sum(final int[] numbers) {
// 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor
for (int i = 0; i < cpuCoreNumber; i++) {
int increment = numbers.length / cpuCoreNumber + 1;
int start = increment * i;
int end = increment * i + increment;
//边界的处理很重要
if (end > numbers.length)
end = numbers.length;
SumCalculator subCalc = new SumCalculator(numbers, start, end);
FutureTask<Long> task = new FutureTask<Long>(subCalc);
tasks.add(task);
if (!exec.isShutdown()) {
exec.submit(task);
}
}
return getResult();
}
/**
* 迭代每个只任务,获得部分和,相加返回
*/
public Long getResult() {
Long result = 0l;
for (Future<Long> task : tasks) {
try {
// 如果计算未完成则阻塞
Long subSum = task.get();
result += subSum;
close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}
public void close() {
exec.shutdown();
}
}
3、普通的方法
import java.util.ArrayList;
import java.util.concurrent.*;
/**
* @author ZFX
* @date2019/3/30 20:09.
*/
public class NumsThread {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10,11,12};
System.out.println(SumMax(arr,3));
}
public static int SumMax(int[] arr, int n){
ExecutorService executorService = Executors.newFixedThreadPool(n);
ArrayList<FutureTask> arrayList = new ArrayList<>();
//注意最后要+1,防止漏加,这点很重要,否则会导致后面元素加不到
int temp = arr.length/n+1;
int start = 0;
int end = 0;
int sum = 0;
for (int i = 0; i <n ; i++) {
start = i*temp;
end = i*temp +temp;
if(end>=arr.length-1)
end = arr.length;
SumRun sumRun = new SumRun(arr,start,end);
FutureTask<Integer> futureTask = new FutureTask(sumRun);
executorService.submit(futureTask);
arrayList.add(futureTask);
}
for (Future<Integer> futureTask : arrayList) {
try {
sum = sum+futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
executorService.shutdown();
return sum;
}
static class SumRun implements Callable<Integer> {
private int start;
private int end;
private int[] arr;
public SumRun(int[] arr,int start,int end){
this.start=start;
this.end=end;
this.arr=arr;
}
private int sum = 0;
@Override
public Integer call() throws Exception {
for (int i = start; i <end ; i++) {
sum+=arr[i];
}
return sum;
}
}
}