Java 异步任务工厂(一)核心架构设计与基础实现
【摘要】 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);
}
}
关键设计点:
- 单例模式:构造函数私有化,通过
me()方法获取唯一实例 - 任务执行:
asyncExecute方法接收Callable任务,提交给执行器运行 - 结果跟踪:返回
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);
}
});
}
}
工厂方法特点:
- 统一封装:每个静态方法对应一个具体业务场景
- 参数灵活:支持设备ID、字段筛选、时间范围等参数
- Spring集成:通过
SpringUtils获取 Mapper 实例 - 异步执行:所有任务都通过
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();
}
}
}
- 准备参数:设备ID和需要查询的字段
- 发起异步任务:调用工厂方法,获得
Future对象 - 获取结果:通过
future.get()获取执行结果
注意:get() 方法会阻塞当前线程,直到任务完成。
6. 优缺点分析
系统优势
| 优势 | 说明 | 实际效果 |
|---|---|---|
| 性能提升 | 异步处理,主线程不阻塞 | 并发能力提升,响应更快 |
| 代码清晰 | 管理和创建职责分离 | 易维护,易扩展 |
| Spring集成 | 无缝对接Spring生态 | 享受依赖注入、事务等特性 |
存在不足
| 问题 | 原因 | 建议改进 |
|---|---|---|
| 线程资源浪费 | 每个任务创建新线程 | 使用 ThreadPoolExecutor 线程池 |
| 异常处理复杂 | 异步异常需要特殊处理 | 封装统一的异常处理机制 |
7. 总结与后续优化
当前,我们搭建了一个简单实用的异步任务工厂,核心特点:
- 简单易用:两个类搞定异步任务管理
- 职责清晰:管理器负责执行,工厂负责创建
- Spring友好:无缝集成现有项目
后续优化方向:
短期优化:
- 替换为
ThreadPoolExecutor线程池 - 增加统一异常处理机制
- 添加任务执行监控
长期规划:
- 引入消息队列(Kafka、RabbitMQ)
- 支持任务优先级和延迟执行
- 增加任务执行统计和报警
这套异步任务工厂虽然简单,但在中小型项目中已经够用。随着业务复杂度提升,再逐步引入更高级的特性即可。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)