Java多用户任务管理系统基于蓝图生成用户专属实例的架构设计咨询
多用户并发任务架构改造方案
核心逻辑是拆分静态配置蓝图和用户侧运行时实例的职责,从根源上避免状态冲突,不需要强行依赖深拷贝实现。
1. 拆分职责层
1.1 只读蓝图层(全局唯一,仅管理员可修改)
这一层对应从数据库/扁平文件加载的任务定义,完全无状态、不可变,全局复用:
- 新增
TaskBlueprint类:存储任务的静态配置,包括所有操作的蓝图集合、首个操作的标识,不包含任何执行相关的状态字段 - 新增
OperationBlueprint接口/类:存储单个操作的静态配置,比如操作类型、执行参数、前后依赖关系等,不包含运行时数据
代码示例:
// 任务蓝图,只读全局复用 public class TaskBlueprint { private final String taskId; private final Map<String, OperationBlueprint> operationBlueprints = new HashMap<>(); private String firstOperationId; // 仅提供get方法,禁止修改配置 public String getFirstOperationId() { return firstOperationId; } public Map<String, OperationBlueprint> getOperationBlueprints() { return Collections.unmodifiableMap(operationBlueprints); } } // 操作蓝图,只读全局复用 public interface OperationBlueprint { // 仅定义执行逻辑,不保存任何实例状态 void execute(User user, UserOperationInstance instance); }
1.2 运行时实例层(每个用户启动任务时生成专属实例)
这一层完全和用户绑定,存储用户专属的执行进度、运行时状态,不同用户的实例完全隔离:
- 新增
UserTaskInstance类:对应用户某次启动的任务实例,存储关联的任务蓝图ID、用户ID、当前执行进度、专属的操作实例集合 - 新增
UserOperationInstance类:对应用户侧单个操作的执行实例,存储关联的操作蓝图ID、执行状态(未开始/运行中/完成/失败)、运行时产生的中间数据、执行时间等动态字段
代码示例:
// 用户任务运行实例,每个用户启动任务时生成 public class UserTaskInstance { private final String taskInstanceId; private final String userId; private final TaskBlueprint taskBlueprint; private final Map<String, UserOperationInstance> operationInstances = new HashMap<>(); private String currentOperationId; // 构造时基于蓝图生成所有专属操作实例 public UserTaskInstance(TaskBlueprint blueprint, String userId) { this.taskBlueprint = blueprint; this.userId = userId; this.currentOperationId = blueprint.getFirstOperationId(); // 基于操作蓝图批量生成用户专属的操作实例 blueprint.getOperationBlueprints().forEach((opId, opBlueprint) -> { operationInstances.put(opId, new UserOperationInstance(opId, userId)); }); } public void startTask(User user) { if (currentOperationId == null) return; UserOperationInstance currentOp = operationInstances.get(currentOperationId); // 执行逻辑从蓝图取,状态存在当前实例里,完全隔离 taskBlueprint.getOperationBlueprints().get(currentOperationId).execute(user, currentOp); } } // 用户操作运行实例,存储单用户操作的专属状态 public class UserOperationInstance { private final String operationId; private final String userId; private int status; // 0未开始 1运行中 2完成 3失败 private Map<String, Object> runtimeParams; // 运行时产生的中间数据 // 提供状态读写方法 public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } }
2. 调整管理器职责
- 原来的
TaskManager仅负责维护全局的TaskBlueprint集合,只提供蓝图查询能力,不涉及任何运行时逻辑 - 新增
UserTaskInstanceManager专门管理用户的任务运行实例:存储所有用户的任务实例,对外提供启动任务、查询进度、暂停恢复任务等接口
代码示例:
public class TaskManager { // 仅存全局只读蓝图 private final Map<String, TaskBlueprint> taskBlueprints = new HashMap<>(); public TaskBlueprint getTaskBlueprint(String taskId) { return taskBlueprints.get(taskId.toLowerCase()); } } public class UserTaskInstanceManager { // 按用户ID+任务实例ID存储,完全隔离 private final Map<String, Map<String, UserTaskInstance>> userTaskInstances = new ConcurrentHashMap<>(); public UserTaskInstance startTask(User user, String taskId) { // 1. 从TaskManager取蓝图 TaskBlueprint blueprint = taskManager.getTaskBlueprint(taskId); if (blueprint == null) throw new IllegalArgumentException("任务不存在"); // 2. 生成用户专属实例 UserTaskInstance instance = new UserTaskInstance(blueprint, user.getUserId()); // 3. 存储实例 userTaskInstances.computeIfAbsent(user.getUserId(), k -> new ConcurrentHashMap<>()) .put(instance.getTaskInstanceId(), instance); // 4. 启动任务 instance.startTask(user); return instance; } }
方案优势
- 无深拷贝带来的维护问题:蓝图全局复用,实例生成逻辑明确,不会出现拷贝漏字段导致的隐性bug
- 状态完全隔离:不同用户的运行实例完全独立,天然支持并发执行,不会出现状态污染
- 扩展性强:后续需要支持任务持久化、暂停恢复、多端同步等能力时,直接对
UserTaskInstance做操作即可,不会影响静态配置层 - 变更风险低:管理员修改蓝图配置后,只会对修改后新启动的任务生效,已经在执行中的用户任务不受影响,符合业务预期
内容的提问来源于stack exchange,提问作者user_020599
相关产品推荐
相关产品推荐

