POM
<!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>29.0-jre</version> </dependency>
package com.vipsoft; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class ListeningExecutorTest { /** * 線程池 */ static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200), new ThreadPoolExecutor.CallerRunsPolicy() ); /** * 數據處理 * * @return * @throws Exception */ public static void main(String[] args) throws Exception { List<String> result = new ArrayList<>(); List<String> list = new ArrayList<>(); //模擬原始數據 for (int i = 0; i < 1211; i++) { list.add(i + "-"); System.out.println("添加原始數據:" + i); } int size = 50;//切分粒度,每size條數據,切分一塊,交由一條線程處理 int countNum = 0;//當前處理到的位置 int count = list.size() / size;//切分塊數 int threadNum = 0;//使用線程數 if (count * size != list.size()) { count++; } final CountDownLatch countDownLatch = new CountDownLatch(count); //使用Guava的ListeningExecutorService裝飾線程池 ListeningExecutorService executorService = MoreExecutors.listeningDecorator(threadPoolExecutor); while (countNum < count * size) { //切割不同的數據塊,分段處理 threadNum++; countNum += size; MyCallable myCallable = new MyCallable(); myCallable.setList(ImmutableList.copyOf(list.subList(countNum - size, list.size() > countNum ? countNum : list.size()))); ListenableFuture listenableFuture = executorService.submit(myCallable); //回調函數 Futures.addCallback(listenableFuture, new FutureCallback<List<String>>() { //任務處理成功時執行 @Override public void onSuccess(List<String> list) { countDownLatch.countDown(); System.out.println("第h次處理完成"); result.addAll(list); } //任務處理失敗時執行 @Override public void onFailure(Throwable throwable) { countDownLatch.countDown(); System.out.println("處理失敗:" + throwable); } },executorService ); } //設置時間,超時了直接向下執行,不再阻塞 countDownLatch.await(3, TimeUnit.SECONDS); result.stream().forEach(s -> System.out.println(s)); System.out.println("------------結果處理完畢,返回完畢,使用線程數量:" + threadNum); } static class MyCallable implements Callable { private List<String> list; @Override public Object call() throws Exception { List<String> listReturn = new ArrayList<>(); //模擬對數據處理,然後返回 for (int i = 0; i < list.size(); i++) { listReturn.add(list.get(i) + ":處理時間:" + System.currentTimeMillis() + "---:處理線程:" + Thread.currentThread()); } return listReturn; } public void setList(List<String> list) { this.list = list; } } }