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);
    }
}


目录
相关文章
|
4天前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
2月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
175 57
|
2月前
|
Java
在Java中实现接口的具体代码示例
可以根据具体的需求,创建更多的类来实现这个接口,以满足不同形状的计算需求。希望这个示例对你理解在 Java 中如何实现接口有所帮助。
98 38
|
1月前
|
数据采集 JSON Java
利用Java获取京东SKU接口指南
本文介绍如何使用Java通过京东API获取商品SKU信息。首先,需注册京东开放平台账号并创建应用以获取AppKey和AppSecret。接着,查阅API文档了解调用方法。明确商品ID后,构建请求参数并通过HTTP客户端发送请求。最后,解析返回的JSON数据提取SKU信息。注意遵守API调用频率限制及数据保护法规。此方法适用于电商平台及其他数据获取场景。
|
1月前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
53 6
|
2月前
|
Java API
Java中内置的函数式接口
Java中内置的函数式接口
39 2
|
2月前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
158 1
|
5月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
152 1
|
8月前
|
设计模式 监控 Java
Java多线程基础-11:工厂模式及代码案例之线程池(一)
本文介绍了Java并发框架中的线程池工具,特别是`java.util.concurrent`包中的`Executors`和`ThreadPoolExecutor`类。线程池通过预先创建并管理一组线程,可以提高多线程任务的效率和响应速度,减少线程创建和销毁的开销。
263 2
|
8月前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
84 1

热门文章

最新文章