ThreadPoolExecutor 除了execute 方法用來提交任務,還有submit 方法,他們的區別就是后者有返回值,其原理是在前者的基礎上使用了Future 接口。因此,我之前的示例改用submit 方法來實現會更加簡單。原因有二:
1、submit 方法提交的任務有返回值,方便判斷每個任務的最終運行結果,無需引入狀態標識變量
2、future 的get方法是阻塞的,無需引入CountDownLatch 並發包工具也可以等待所有線程運行完畢
直接上代碼
package com.yzy.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; public class Main2 { public static void main(String[] args) throws ExecutionException, InterruptedException { // 線程安全的計數器 AtomicInteger totalRows = new AtomicInteger(0); // 創建線程池,其中核心線程10,也是我期望的最大並發數,最大線程數和隊列大小都為30,即我的總任務數 ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 30, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(30)); // 創建 Future 集合,用來存儲Future 實例 List<Future<Integer>> futureList = new ArrayList<>(); for (int i = 0; i < 30; i++) { final int index = i; // 這里創建 Callable 實例,返回整型 Future<Integer> future = executor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { // 模擬異常的線程,返回0 if (index % 5 == 0) { return 0; } int times = 0; boolean loop = true; // 模擬數據拉取過程可能需要分頁 while (loop) { // 模擬每個任務需要分頁5次 if (times >= 5) { break; } times++; // 模擬計數 totalRows.incrementAndGet(); // 模擬耗時 try { // 打印運行情況 System.out.println(Thread.currentThread().getName() + ":" + index + ":" + times); Thread.sleep(Long.valueOf(String.valueOf(new Double(Math.random() * 1000).intValue()))); } catch (InterruptedException e) { e.printStackTrace(); } } // 成功返回1 return 1; } }); futureList.add(future); } // 標記多線程關閉,但不會立馬關閉 executor.shutdown(); boolean flag = true; for (Future<Integer> future : futureList) { // 獲取每一個線程的返回結果,如果該線程未完成,會阻塞 if (future.get() == 0) { flag = false; } } if (flag) { System.out.println("全部成功了,計數:" + totalRows.get()); } else { System.out.println("失敗了"); } } }
運行結果
//省略若干行 pool-1-thread-7:24:5 pool-1-thread-3:29:3 pool-1-thread-3:29:4 pool-1-thread-5:28:3 pool-1-thread-6:26:4 pool-1-thread-6:26:5 pool-1-thread-5:28:4 pool-1-thread-5:28:5 pool-1-thread-3:29:5 失敗了
然后注釋這部分代碼
if (index % 5 == 0) { return 0; }
再次運行:
//省略若干行 pool-1-thread-7:24:4 pool-1-thread-7:24:5 pool-1-thread-1:26:5 pool-1-thread-8:25:4 pool-1-thread-8:25:5 pool-1-thread-3:29:4 pool-1-thread-3:29:5 全部成功了,計數:150
鏈接:https://www.jianshu.com/p/4060dd274dbd