Java多线程Future与CompletableFuture-异步获取接口返回结果

简介: 当调用一些耗时接口时,如果我们一直在原地等待方法返回,整体程序的运行效率会大大降低。可以把调用的过程放到子线程去执行,再通过 Future 去控制子线程的调用过程,最后获取到调用结果,来提高整个程序的运行效率。

背景:

当调用一些耗时接口时,如果我们一直在原地等待方法返回,整体程序的运行效率会大大降低。可以把调用的过程放到子线程去执行,再通过 Future 去控制子线程的调用过程,最后获取到计算结果。提高整个程序的运行效率。

创建线程池:

@ConfigurationpublicclassExecutorConfig {
privatefinalstaticintTHREAD_COUNT=Runtime.getRuntime().availableProcessors() *2;
@Bean(name="batchCallThreadPool")
publicThreadPoolExecutorbatchPredictThreadPool() {
returnnewThreadPoolExecutor(THREAD_COUNT, 200, 0L, TimeUnit.MILLISECONDS, newLinkedBlockingQueue<Runnable>(2048),
newThreadFactoryBuilder().setNameFormat("batch-call-pool-%d").build());
    }
}

利用Future获取线程执行结果

importjava.util.List;
importjava.util.Map;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.Future;
importjava.util.concurrent.ThreadPoolExecutor;
importjava.util.concurrent.TimeUnit;
importjava.util.concurrent.TimeoutException;
importcom.google.common.collect.Maps;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Qualifier;
publicclassFutureTestService {
@AutowiredprivateCallServicecallService;
@Autowired@Qualifier("batchPredictThreadPool")
privateThreadPoolExecutorbatchPredictThreadPool;
publicvoidfun(List<Long>idList) {
Map<Long, Future<Integer>>futureMap=Maps.newHashMapWithExpectedSize(idList.size());
// 让所有调用的子线程启动,参与竞争for (Longid : idList) {
Future<Integer>future=batchPredictThreadPool.submit(() ->callService.call(id));
futureMap.put(id, future);
        }
for (Longid : futureMap.keySet()) {
try {
// 阻塞获取执行结果,如果 3s 未获取到会抛出超时异常Integerresult=futureMap.get(id).get(3000, TimeUnit.MILLISECONDS);
            } catch (TimeoutExceptione) {
// 处理超时            } catch (ExecutionExceptione) {
// 处理执行时异常            } catch (InterruptedExceptione) {
// 处理 中断            }
        }
    }
}

利用CompletableFuture获取线程执行结果

importjava.util.HashMap;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.Map;
importjava.util.concurrent.CompletableFuture;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.ThreadPoolExecutor;
importjava.util.concurrent.TimeUnit;
importjava.util.concurrent.TimeoutException;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Qualifier;
publicclassFutureTestService {
@AutowiredprivateCallServicecallService;
@Autowired@Qualifier("batchPredictThreadPool")
privateThreadPoolExecutorbatchPredictThreadPool;
publicvoidfun(List<Long>idList) throwsExecutionException, InterruptedException, TimeoutException {
List<CompletableFuture<Integer>>completableFutureList=newLinkedList<>();
Map<Long, Integer>resultMap=newHashMap<>(idList.size());
// 让所有调用的子线程启动,参与竞争for (Longid : idList) {
CompletableFuture<Integer>future=CompletableFuture.supplyAsync(() -> {
Integerresult=callService.call(id);
resultMap.put(id, result);
returnnull;
            }, batchPredictThreadPool);
completableFutureList.add(future);
        }
// 在此处聚合CompletableFuture<Void>allCompletableFuture=CompletableFuture.allOf(completableFutureList.toArray(
newCompletableFuture[completableFutureList.size()]));
/*** 如果在 3 秒钟之内这些任务都可以顺利返回,则这个 get 方法就可以及时正常返回,并且往下执行。* 如果有某一个任务没能来得及在 3 秒钟之内返回,那么这个带超时参数的 get 方法便会抛出 TimeoutException 异常* 会尝试等待所有的任务完成,但是最多只会等 3 秒钟,在此之间,如及时完成则及时返回。*/allCompletableFuture.get(3, TimeUnit.SECONDS);
    }
}


目录
相关文章
|
2天前
|
安全 Java 开发者
Java并发编程中的线程安全性与性能优化
在Java编程中,处理并发问题是至关重要的。本文探讨了Java中线程安全性的概念及其在性能优化中的重要性。通过深入分析多线程环境下的共享资源访问问题,结合常见的并发控制手段和性能优化技巧,帮助开发者更好地理解和应对Java程序中的并发挑战。 【7月更文挑战第14天】
|
2天前
|
监控 Java API
Java并发编程之线程池深度解析
【7月更文挑战第14天】在Java并发编程领域,线程池是提升性能、管理资源的关键工具。本文将深入探讨线程池的核心概念、内部工作原理以及如何有效使用线程池来处理并发任务,旨在为读者提供一套完整的线程池使用和优化策略。
|
3天前
|
Java 调度
java中线程的6种状态
java中线程的6种状态
|
7天前
|
Java
实现Java多线程中的线程间通信
实现Java多线程中的线程间通信
|
5天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
18 1
|
5天前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
15 1
|
4天前
|
缓存 Linux 编译器
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
11 0
|
4天前
|
存储 Linux 调度
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
14 0
|
5天前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
12 0
|
5天前
|
设计模式 安全 NoSQL
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
13 0