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个月内不可修改。