jdk1.7后提供多线程多任务拆分子任务
List<GpsCoordHistroy> datalistCar ; //方式2:多任务方式 SumTask task = new SumTask(datalistCar, kafkaTemplate, 0, datalistCar.size()); //创建一个通用池,这个是jdk1.8提供的功能 ForkJoinPool pool = ForkJoinPool.commonPool(); //提交分解的SumTask 任务 Future<Integer> future = pool.submit(task); try { long e = System.currentTimeMillis(); logger.warn("当前线程处理数量:" +future.get()+"原始数据量:"+ datalistCar.size() + "共耗时" + (e - s) + "毫秒"); } catch (Exception e) { e.printStackTrace(); } finally { //关闭线程池 pool.shutdown(); }
/** * 多线程同步处理大任务拆分子任务方式 */ public class SumTask extends RecursiveTask<Integer> { /** * 每个小任务 最多只累加1000个 */ private static final int THRESHOLD = 1000; private Logger logger = LoggerFactory.getLogger(getClass()); private KafkaTemplate kafkaTemplate; private List<GpsCoordHistroy> datalist; /** * 任务集合开始点 */ private int start; /** * 任务集合结束点 */ private int end; public SumTask(List<GpsCoordHistroy> datalist, KafkaTemplate kafkaTemplate, int start, int end) { this.datalist = datalist; this.kafkaTemplate = kafkaTemplate; this.start = start; this.end = end; } @Override protected Integer compute() { if (end-start <= THRESHOLD) { sendKafKa(datalist.subList(start,end)); return end-start; } else { int middle = (start+ end)/2; SumTask left = new SumTask(datalist,kafkaTemplate, start, middle); SumTask right = new SumTask(datalist,kafkaTemplate, middle, end); //并行执行两个 小任务 left.fork(); right.fork(); //把两个小任务累加的结果合并起来 return left.join()+right.join(); } }
private void sendKafKa(List<GpsCoordHistroy> currentList) {}
虽说了ForkJoinPool会把大任务拆分成多个子任务,但是ForkJoinPool并不会为每个子任务创建单独的线程。相反,池中每个线程都有自己的双端队列(Deque)用于存储任务。这个双端队列对于工作窃取算法至关重要。