Java 异步任务工厂(一)核心架构设计与基础实现

举报
Yeats_Liao 发表于 2025/11/05 14:20:41 2025/11/05
【摘要】 1. 为什么需要异步任务工厂?想象一下这个场景:你的系统需要同时查询用户信息、订单数据、商品详情,如果一个个查询,用户得等好几秒才能看到页面。但如果让这些查询同时进行,几百毫秒就搞定了。这就是异步编程的魅力。今天我们来看看如何用 Java 搭建一个实用的异步任务工厂,主要包含 AsyncManager(任务管理器)和 AsyncFactory(任务工厂)两个核心组件。 2. 异步编程核心概...

1. 为什么需要异步任务工厂?

想象一下这个场景:你的系统需要同时查询用户信息、订单数据、商品详情,如果一个个查询,用户得等好几秒才能看到页面。但如果让这些查询同时进行,几百毫秒就搞定了。

这就是异步编程的魅力。今天我们来看看如何用 Java 搭建一个实用的异步任务工厂,主要包含 AsyncManager(任务管理器)和 AsyncFactory(任务工厂)两个核心组件。


2. 异步编程核心概念

2.1 同步 vs 异步:排队买咖啡的故事

同步方式:就像在咖啡店排队,前面的人不买完,你就得一直等着。程序也一样,一个任务不完成,后面的都得等。

异步方式:就像点外卖,下单后你可以继续做其他事,外卖到了会通知你。程序执行耗时任务时,不用干等,可以处理其他请求。

2.2 线程池:工人管理系统

线程池就像一个工人管理系统:

  • 避免频繁招聘解雇工人(创建销毁线程)的成本
  • 根据工作量调整工人数量
  • 让工人复用,提高效率

Java 中常用的有:

  • ExecutorService:普通线程池
  • ScheduledExecutorService:定时任务线程池

2.3 Future:任务回执单

Future 就像你的任务回执单:

  • 可以查看任务是否完成
  • 获取任务执行结果
  • 必要时取消任务

3. 系统架构设计

3.1 整体架构:分工明确的二人组

我们的异步系统就像一个配合默契的二人组:

  • AsyncManager(管理员):负责管理和执行所有异步任务
  • AsyncFactory(工厂师傅):负责生产各种具体的异步任务

3.2 AsyncManager:单例模式的任务管理员

特点:
✓ 全局唯一实例(单例模式)
✓ 使用 SimpleAsyncTaskExecutor 执行任务
✓ 为每个任务分配独立线程

主要职责:
• 提供统一的任务执行入口
• 返回 Future 对象跟踪任务状态

3.3 AsyncFactory:任务生产工厂

特点:
✓ 工具类设计,全部静态方法
✓ 封装具体业务逻辑
✓ 统一调用 AsyncManager 执行

支持的任务类型:
• 获取设备基本信息
• 查询设备实时数据
• 获取设备历史记录
• 其他设备相关操作

4. 核心代码实现

4.1 AsyncManager:任务管理核心

package com.example.async.schedule;

import com.example.common.utils.spring.SpringUtils;
import org.springframework.core.task.SimpleAsyncTaskExecutor;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * 异步任务管理器
 */
public class AsyncManager {
    private static AsyncManager me = new AsyncManager();
    private SimpleAsyncTaskExecutor asyncTaskExecutor = SpringUtils.getBean("asyncTask");

    /**
     * 单例模式
     */
    private AsyncManager() {
    }

    /**
     * 获取单例实例
     * @return AsyncManager 实例
     */
    public static AsyncManager me() {
        return me;
    }

    /**
     * 异步执行任务
     * @param task 任务
     * @param <T> 任务返回值类型
     * @return 任务执行结果的 Future 对象
     */
    public <T> Future<T> asyncExecute(Callable<T> task) {
        return asyncTaskExecutor.submit(task);
    }
}

关键设计点:

  1. 单例模式:构造函数私有化,通过 me() 方法获取唯一实例
  2. 任务执行asyncExecute 方法接收 Callable 任务,提交给执行器运行
  3. 结果跟踪:返回 Future 对象,方便获取执行结果

4.2 AsyncFactory:任务工厂实现

package com.example.async.schedule;

import com.example.entity.Device;
import com.example.entity.DeviceData;
import com.example.mapper.DeviceDataMapper;
import com.example.mapper.DeviceMapper;
import com.example.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

/**
 * 异步工厂(产生任务用)
 */
@Slf4j
public class AsyncFactory {

    /**
     * 异步获取设备信息
     * @param deviceId 设备 ID
     * @param validFields 设备有效字段
     * @return 设备信息的 Future 对象
     */
    public static Future<Device> asyncGetDeviceInfo(Long deviceId, List<String> validFields) {
        return AsyncManager.me().asyncExecute(new Callable<Device>() {
            @Override
            public Device call() throws Exception {
                return SpringUtils.getBean(DeviceMapper.class).getDeviceInfoById(deviceId, validFields);
            }
        });
    }

    /**
     * 异步获取设备数据
     * @param deviceId 设备 ID
     * @param dataFields 设备数据有效字段
     * @return 设备数据的 Future 对象
     */
    public static Future<DeviceData> asyncGetDeviceData(Long deviceId, List<String> dataFields) {
        return AsyncManager.me().asyncExecute(
                new Callable<DeviceData>() {
                    @Override
                    public DeviceData call() throws Exception {
                        return SpringUtils.getBean(DeviceDataMapper.class).getDeviceDataById(deviceId, dataFields);
                    }
                });
    }

    /**
     * 异步获取无限制的设备数据
     * @param deviceId 设备 ID
     * @param dataFields 设备数据有效字段
     * @return 设备数据的 Future 对象
     */
    public static Future<DeviceData> asyncGetDeviceDataNoLimit(Long deviceId, List<String> dataFields) {
        return AsyncManager.me().asyncExecute(
                new Callable<DeviceData>() {
                    @Override
                    public DeviceData call() throws Exception {
                        return SpringUtils.getBean(DeviceDataMapper.class).getDeviceDataByIdNoLimit(deviceId, dataFields);
                    }
                });
    }

    /**
     * 异步获取设备历史记录
     * @param deviceId 设备 ID
     * @param validFields 设备有效字段
     * @param days 天数
     * @return 设备历史记录列表的 Future 对象
     */
    public static Future<List<DeviceData>> asyncGetDeviceHistoryData(Long deviceId, List<String> validFields, Integer days) {
        return AsyncManager.me().asyncExecute(
                new Callable<List<DeviceData>>() {
                    @Override
                    public List<DeviceData> call() throws Exception {
                        return SpringUtils.getBean(DeviceDataMapper.class).getDeviceHistoryDataById(deviceId, validFields, days);
                    }
                });
    }

    /**
     * 异步获取设备最新历史记录
     * @param deviceId 设备 ID
     * @param validFields 设备有效字段
     * @param count 数量
     * @return 设备最新历史记录列表的 Future 对象
     */
    public static Future<List<DeviceData>> asyncGetDeviceNewHistoryData(Long deviceId, List<String> validFields, Integer count) {
        return AsyncManager.me().asyncExecute(
                new Callable<List<DeviceData>>() {
                    @Override
                    public List<DeviceData> call() throws Exception {
                        return SpringUtils.getBean(DeviceDataMapper.class).getDeviceNewHistoryDataById(deviceId, validFields, count);
                    }
                });
    }
}

工厂方法特点:

  1. 统一封装:每个静态方法对应一个具体业务场景
  2. 参数灵活:支持设备ID、字段筛选、时间范围等参数
  3. Spring集成:通过 SpringUtils 获取 Mapper 实例
  4. 异步执行:所有任务都通过 AsyncManager 异步执行

5. 实际使用案例

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;

public class Main {
    public static void main(String[] args) {
        Long deviceId = 1L;
        List<String> validFields = Arrays.asList("field1", "field2");

        // 异步获取设备信息
        Future<Device> deviceFuture = AsyncFactory.asyncGetDeviceInfo(deviceId, validFields);

        // 异步获取设备数据
        Future<DeviceData> deviceDataFuture = AsyncFactory.asyncGetDeviceData(deviceId, validFields);

        try {
            // 获取设备信息
            Device device = deviceFuture.get();
            System.out.println("Device Info: " + device);

            // 获取设备数据
            DeviceData deviceData = deviceDataFuture.get();
            System.out.println("Device Data: " + deviceData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 准备参数:设备ID和需要查询的字段
  2. 发起异步任务:调用工厂方法,获得 Future 对象
  3. 获取结果:通过 future.get() 获取执行结果

注意get() 方法会阻塞当前线程,直到任务完成。


6. 优缺点分析

系统优势

优势 说明 实际效果
性能提升 异步处理,主线程不阻塞 并发能力提升,响应更快
代码清晰 管理和创建职责分离 易维护,易扩展
Spring集成 无缝对接Spring生态 享受依赖注入、事务等特性

存在不足

问题 原因 建议改进
线程资源浪费 每个任务创建新线程 使用 ThreadPoolExecutor 线程池
异常处理复杂 异步异常需要特殊处理 封装统一的异常处理机制

7. 总结与后续优化

当前,我们搭建了一个简单实用的异步任务工厂,核心特点:

  • 简单易用:两个类搞定异步任务管理
  • 职责清晰:管理器负责执行,工厂负责创建
  • Spring友好:无缝集成现有项目

后续优化方向:

短期优化:

  • 替换为 ThreadPoolExecutor 线程池
  • 增加统一异常处理机制
  • 添加任务执行监控

长期规划:

  • 引入消息队列(Kafka、RabbitMQ)
  • 支持任务优先级和延迟执行
  • 增加任务执行统计和报警

这套异步任务工厂虽然简单,但在中小型项目中已经够用。随着业务复杂度提升,再逐步引入更高级的特性即可。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。