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)用於存儲任務。這個雙端隊列對於工作竊取算法至關重要。