executor 线程查询数据和整合数据,CompletableFuture.supplyAsync 的应用

查询接口,发现需要查询大量的sql,导致返回的时间超长,并且有多个循环查找。
可以用多线程方式进行查询

// 创建要调用的实体类或者方法;这个类随自己的逻辑进行修改
public class PayDataStatisticsProcessor implements Runnable{
	// 服务类,不需要再注入
	private PayDataStatisticsService payDataStatisticsService;
	// redis工具,用到就写上
    private RedisUtil redisUtil;
    // 实体类
    private ModelStatis modelStatis ;
    // 返回的实体
    private List<ModelStatis > resultList;
    // 查询条件,封装在实体里
    private ModelStatisQuery modelStatisQuery ;
    // 金额格式化
    private DecimalFormat df = new DecimalFormat("##,##0.00");
    // 构造函数 这样就不需要get、set 方法了
     public PayDataStatisticsProcessor(PayDataStatisticsService payDataStatisticsService, RedisUtil redisUtil, ModelStatis modelStatis, List<ModelStatis > resultList, ModelStatisQuery modelStatisQuery ) {
      this.payDataStatisticsService = payDataStatisticsService;
      this.redisUtil = redisUtil;
      this.modelStatis = modelStatis;
      this.resultList = resultList;
      this.modelStatisQuery = modelStatisQuery ;
     }
     // 重写线程方法
     @Override
    public void run() {
    	ModelStatis result = new ModelStatis ();
    	// 一堆逻辑

		// 同步方法;一定要加
    	synchronized (resultList){
            resultList.add(result);
        }
    }
}

// 调用方式
 int numThreads = 6; // 定义线程数
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);
for (int i = 0; i < 8; i++) {
 PayDataStatisticsProcessor processor = new PayDataStatisticsProcessor(构造方法要传的参数);
	 executor.execute(processor);
}
	// 关闭线程池 记得要关闭
  executor.shutdown();
  // 线程执行是否完成,没完成继续执行
  while (!executor.isTerminated()) {
       // 等待所有任务执行完成
       Thread.sleep(100);
       System.out.println("等待所有线程执行完成,等待时间100ms");
   }
<think>好的,我现在需要帮助用户理解他们提供的Java代码的功能实现逻辑。首先,用户的问题是关于一段特定的Java代码,他们希望了解这段代码的具体作用,特别是涉及到的CompletableFuture.runAsync的使用以及整体逻辑。 首先,我应该回顾用户提供的代码段: ```java delayInitialTime = delayInitialTime < 5 ? 5 : delayInitialTime; if (secsCommHost.getType().equalsIgnoreCase("TOOL")) { CompletableFuture.runAsync(() -> { logger.info("===== {} Initialization start async =====", engineName); toolInitializeService.offline2online(engineName); logger.info("===== {} Initialization finished =====.", engineName); ouiOperUtils.updateCommLinkState(engineName); }, FutureDelay.delayedExecutor(delayInitialTime, TimeUnit.SECONDS)); } ``` 接下来,我需要分解这段代码的各个部分,逐一解释它们的功能。用户特别提到要关注CompletableFuture.runAsync的用法以及整体功能,所以这部分需要详细说明。 首先,第一行代码使用了三元运算符来确保delayInitialTime的值不小于5。这看起来是一个延迟时间的下限设置,防止设置过小的延迟时间。例如,如果delayInitialTime原本是3,会被设置为5;如果是7,则保持不变。 接下来是一个条件判断,检查secsCommHost的类型是否为"TOOL",这里使用了equalsIgnoreCase,说明不区分大小写。如果条件满足,则进入代码块执行异步任务。 在异步任务部分,使用了CompletableFuture.runAsync方法,传递了一个Runnable任务一个自定义的延迟执行器(通过FutureDelay.delayedExecutor方法创建)。任务内部包含日志记录、调用offline2online方法,以及更新通信链路状态的操作。 我需要解释CompletableFuture.runAsync的作用,即异步执行任务,并且在这里结合了延迟执行器,使得任务在指定的延迟时间后执行。同时,要说明为什么需要异步执行,比如避免阻塞主线程,提高程序的响应性。 另外,用户提到的引用内容中,有关Java线程程序计数器的部分,可能代码中的异步执行有关,可以适当引用来说明线程切换任务恢复的机制。例如,当异步任务被延迟执行时,线程可能会被挂起,等待延迟结束后再恢复执行,这时程序计数器的作用就体现出来了,确保任务从正确的位置继续执行。 此外,用户之前的问题中提到了日志记录延迟执行的两种方式(Thread.sleepScheduledExecutorService),这里使用的是自定义的延迟执行器,可能基于ScheduledExecutorService实现,因此需要指出这种方式的优势,比如非阻塞更好的资源管理。 还需要注意用户提供的引用[3][4]中提到的JAVA_TOOL_OPTIONS环境变量的问题,但这段代码似乎没有直接关联,可能不需要深入讨论,除非用户有其他意图。 在整体功能方面,这段代码似乎是在某个服务或工具初始化时,根据主机类型触发异步的初始化过程,确保在至少5秒的延迟后执行,同时记录日志并更新状态。这可能用于系统启动时的模块初始化,或者在某种条件满足后延迟加载某些功能,以避免资源竞争或提高启动性能。 需要确认用户是否理解异步编程的基本概念,比如非阻塞执行线程池的使用,以及CompletableFuture的常见方法(如runAsync与supplyAsync的区别)。不过根据用户的问题,他们更关注当前代码的具体实现,所以应集中在现有代码的分析上。 最后,确保回答结构清晰,分点解释每个部分的功能,并整合整体逻辑。同时,参考用户之前的问题回答,保持一致性,比如之前提到的日志配置、异步任务处理等,可以适当链接相关内容,帮助用户形成完整的知识体系。</think>### Java代码功能解析(修订版) #### 一、核心代码功能分解 ```java // 1. 延迟时间下限控制 delayInitialTime = delayInitialTime < 5 ? 5 : delayInitialTime; // 2. 类型检查与异步任务触发 if (secsCommHost.getType().equalsIgnoreCase("TOOL")) { // 3. 构建延迟异步任务 CompletableFuture.runAsync(() -> { logger.info("===== {} Initialization start async =====", engineName); toolInitializeService.offline2online(engineName); logger.info("===== {} Initialization finished =====.", engineName); ouiOperUtils.updateCommLinkState(engineName); }, FutureDelay.delayedExecutor(delayInitialTime, TimeUnit.SECONDS)); // 关键点 } ``` --- #### 二、关键技术点详解 ##### 1. **延迟时间下限控制** - **实现机制**:三元运算符强制设置最小延迟时间为5秒 `delayInitialTime < 5 ? 5 : delayInitialTime` 等价于: ```java if (delayInitialTime < 5) { delayInitialTime = 5; } ``` - **必要性**:防止过短的延迟导致初始化任务与主线程资源竞争(如数据库连接池未完成初始化时提前访问)[^1] ##### 2. **CompletableFuture.runAsync 进阶** - **延迟执行器原理**: `FutureDelay.delayedExecutor` 内部实现一般基于 `ScheduledExecutorService`: ```java public static Executor delayedExecutor(long delay, TimeUnit unit) { return CompletableFuture.delayedExecutor(delay, unit); } ``` 实际产生一个包装后的 `Executor`,通过 `ScheduledThreadPool` 实现非阻塞延迟[^2] - **与直接使用线程池的区别**: ```java // 传统方式需手动管理线程池 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.schedule(() -> { /* 任务 */ }, delay, TimeUnit.SECONDS); ``` `CompletableFuture` 方式自动整合到异步编程框架中,支持更便捷的链式调用 ##### 3. **初始化流程时序** ```mermaid sequenceDiagram 主线程->>+线程池: 提交延迟异步任务线程-->>主业务: 继续执行其他代码 线程池->>+延迟队列: 等待delayInitialTime秒 延迟队列-->>线程池: 释放任务 线程池->>+工具服务: 执行offline2online() 工具服务-->>-线程池: 返回结果 线程池->>+状态服务: updateCommLinkState() 状态服务-->>-线程池: 更新完成 ``` --- #### 三、多线程上下文关联(结合引用[1]) 当异步任务被延迟执行时,Java虚拟机会通过 **程序计数器(PC寄存器)** 保存当前线程执行位置。在延迟结束后,线程池中的工作线程会从线程私有内存中恢复以下关键数据: 1. 方法调用栈帧(局部变量表、操作数栈) 2. 当前执行的字节码指令地址 3. 异步任务中引用的 `engineName` 等对象引用 这种机制使得异步任务恢复时能准确衔接上下文,避免因线程切换导致状态丢失[^1]。 --- #### 四、典型应用场景 1. **服务热切换**: - 在线升级时,先通过 `offline2online` 将旧实例状态迁移到新实例 - 延迟确保旧请求处理完毕 - 更新链路状态完成平滑过渡 2. **硬件设备初始化**: - 工业控制系统中,设备上电后延迟执行自检 - 避免瞬时电流波动导致误检 --- ### 相关问题 1. 如何通过 `CompletableFuture` 实现异步任务的超时控制? 2. `offline2online` 方法是否需要考虑线程安全问题?如何验证? 3. 如果 `FutureDelay.delayedExecutor` 不可用,如何用原生API实现相同功能?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值