版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20009015/article/details/89913091
@Override
public List<TaxForeDTO> getTaxForeForkJoin(List<String> organizeId, String uid, Date Begin, Date end)
throws Exception {
Long begintime=System.currentTimeMillis();
//cpu+io总耗时23秒 io时间21秒
//最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
//21/2+1
int nums= 11*Runtime.getRuntime().availableProcessors();
log.info("线程数{}",organizeId.size());
// ForkJoinPool forkjoinPool = new ForkJoinPool(nums);
ForkJoinPool forkjoinPool = new ForkJoinPool(organizeId.size());
//生成一个计算任务
ForkJoinTaskExample task = new ForkJoinTaskExample(organizeId, uid,Begin,end);
//执行一个任务
Future<List<TaxForeDTO>> result = forkjoinPool.submit(task);
List<TaxForeDTO> list=new ArrayList<>();
try {
list=result.get();
log.info("result:{}", list);
} catch (Exception e) {
log.error("exception", e);
}
Long endtime=System.currentTimeMillis();
log.info("预测表并行开始时间{},结束时间{},总耗时{},秒数{}", begintime,endtime, endtime-begintime,(endtime-begintime)/1000.0f);
return list;
}
class ForkJoinTaskExample extends RecursiveTask<List<TaxForeDTO>> {
public final int threshold = 2;
private List<String> organizeId;
private String uid;
private Date Begin;
private Date endDate;
private int start;
private int end;
public ForkJoinTaskExample(List<String> organizeId, String uid, Date begin, Date end) {
this.organizeId = organizeId;
this.uid = uid;
this.Begin = begin;
this.endDate = end;
this.start=0;
this.end=organizeId.size()-1;
}
@Override
protected List<TaxForeDTO> compute() {
List<TaxForeDTO> sum=new ArrayList<>();
//如果任务足够小就计算任务
boolean canCompute = (end - start) <=threshold;
if (canCompute) {
try {
sum.addAll(getTaxFore(organizeId.subList(start,end),uid,Begin,endDate));
} catch (Exception e) {
e.printStackTrace();
}
} else {
// 如果任务大于阈值,就分裂成两个子任务计算
int middle = (start + end) / 2;
ForkJoinTaskExample leftTask = new ForkJoinTaskExample(organizeId.subList(start,middle),uid,Begin,endDate);
ForkJoinTaskExample rightTask = new ForkJoinTaskExample(organizeId.subList(middle+1,end),uid,Begin,endDate);
// 执行子任务
leftTask.fork();
rightTask.fork();
// 等待任务执行结束合并其结果
List<TaxForeDTO> leftResult = leftTask.join();
List<TaxForeDTO> rightResult = rightTask.join();
// 合并子任务
sum.addAll(leftResult);
sum.addAll(rightResult);
}
return sum;
}
}
这里注意下 ,想查询sql这种,因为发起请求之后 要等待数据库的返回,大部分时间其实是在等待io。 这种频繁等待io的操作 是io密集型,这个时候设置的线程数
可以粗略的设置成2*N (N为cpu核心数 可以用Runtime.getRuntime().availableProcessors() 获取) ,或者设置成(总时间/cpu时间)*N 总时间是指cpu时间+等待io时间
如果是cpu密集型任务,则线程数设置为N+1就差不多了,再多 也会因为上下文切换而浪费时间,而且 cpu也不堪重负。