保证子线程中事务的一致性

0 前沿

逻辑如下:
① 主线程新增数据库表A记录,状态为新增中
② 子线程去读txt中的数据,读取失败,更新表A的状态为失败;读取成功:1)更新表A状态为成功;2)将txt数据新增到表B;3)新增基础信息到表C

1 代码

XXXImpl:

@Resource
private DataMapper dataMapper;

@Resource
private DataAsyncService dataAsyncService;

String fileName = file.getOriginalFilename();
 // 新增标准格式记录
 dataMapper.addRecord(importModel);
 // 异步读取文件中的数据
 ExecutorService executor = Executors.newCachedThreadPool();
 executor.submit(() -> {
     try {
         dataAsyncService.asyncAddDataHandle(model, file, fileName, importModel);
     } catch (Exception e) {
         dataMapper.updateRecord(importModel.getId(), ImportStatus.FAIL.getCode(), null);
         log.error("文件读取失败:{}", e.getMessage());
         Thread.currentThread().interrupt();
     } finally {
         executor.shutdownNow();
     }
 });
 return AjaxResult.success();

DataAsyncServiceImpl:

@Transactional
public void asyncAddDataHandle() {
  try {
      // 附件读取
      DataResult dataResult = FileReadUtils.readData(file);
      // 新增基础数据
      dataMapper.addBase(model);
      // 更新记录
      dataMapper.updateRecord(importModel.getId(), ImportStatus.SUCCESS.getCode(), fileModel.getFilePath());
      // 新增txt数据
      dataMapper.addFileData(models);
  } catch (Exception e) {
      throw new BusinessException(e.getMessage());
  }
}

2 说明

1)DataAsyncServiceImpl中的asyncAddDataHandle方法如果写到XXXImpl会回滚不了,原因:
① 事务注解生效条件:@Transactional注解的方法必须是public,且由 Spring 容器管理(不能是 private/protected,不能在同类中直接调用,需通过 Bean 注入调用)。
② 异常处理:异步方法中需捕获异常并重新抛出,否则 Spring 无法感知异常,事务不会回滚。
2)或者可以尝试在XXXImpl中注入自身,然后把asyncAddDataHandle方法写在XXXImpl中
3)也可以使用 Spring 的@Async替代手动创建线程池,没尝试
4)如若此方法存在其他问题,麻烦在评论区中给出

内容概要:本文介绍了一个基于Matlab的综合能源系统优化调度仿真资源,重点实现了含光热电站、有机朗肯循环(ORC)和电含光热电站、有机有机朗肯循环、P2G的综合能源优化调度(Matlab代码实现)转气(P2G)技术的冷、热、电多能互补系统的优化调度模型。该模型充分考虑多种能源形式的协同转换与利用,通过Matlab代码构建系统架构、设定约束条件并求解优化目标,旨在提升综合能源系统的运行效率与经济性,同时兼顾灵活性供需不确定性下的储能优化配置问题。文中还提到了相关仿真技术支持,如YALMIP工具包的应用,适用于复杂能源系统的建模与求解。; 适合人群:具备一定Matlab编程基础和能源系统背景知识的科研人员、研究生及工程技术人员,尤其适合从事综合能源系统、可再生能源利用、电力系统优化等方向的研究者。; 使用场景及目标:①研究含光热、ORC和P2G的多能系统协调调度机制;②开展考虑不确定性的储能优化配置与经济调度仿真;③学习Matlab在能源系统优化中的建模与求解方法,复现高水平论文(如EI期刊)中的算法案例。; 阅读建议:建议读者结合文档提供的网盘资源,下载完整代码和案例文件,按照目录顺序逐步学习,重点关注模型构建逻辑、约束设置与求解器调用方式,并通过修改参数进行仿真实验,加深对综合能源系统优化调度的理解。
多线程环境下保证数据库事务的一致性是一个复杂且关键的问题,尤其是在涉及并发操作和分布式资源管理的场景中。以下是一些常见的方法和技术: ### 1. 使用事务传播属性 通过合理配置事务的传播属性,可以控制事务的边界如何在多个线程之间传播。例如,在Spring框架中,可以通过`@Transactional(propagation = Propagation.REQUIRES_NEW)`来确保每个线程都有自己的事务上下文[^1]。 ### 2. 线程等待机制 为了确保所有线程的操作都成功完成后再提交事务,可以在所有线程执行完各自的DML语句后进行统一的commit或rollback操作。这种方式需要线程之间的协调,例如使用CountDownLatch或者Future来实现线程间的等待和同步[^2]。 ### 3. ThreadLocal绑定资源 在多线程环境中,将数据库连接(Connection)绑定到当前线程的ThreadLocal变量中是一种常见的做法。这样可以避免连接在不同线程间共享导致的冲突问题。Spring框架中的TransactionSynchronizationManager就是利用ThreadLocal来保存事务相关的资源[^3]。 ### 4. 异常处理与回滚机制 在多线程任务中,如果任何一个线程抛出异常,则应触发整个事务的回滚操作。这要求开发者在设计任务时考虑到异常处理,并确保所有线程的操作是原子性的。例如,通过自定义的事务管理器捕获所有线程的异常并决定是否回滚事务[^4]。 ### 5. 使用分布式事务管理器 对于跨服务或多数据源的情况,可能需要引入分布式事务管理器(如Atomikos、Bitronix等),这些工具支持XA协议,能够协调多个资源管理器之间的事务一致性。 ### 示例代码:线程等待机制 ```java import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TransactionConsistencyExample { private static final int THREAD_COUNT = 2; private static CountDownLatch latch = new CountDownLatch(THREAD_COUNT); public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT); // 模拟两个线程的任务 Runnable task1 = () -> { try { // 执行DML操作 System.out.println("Thread 1 is executing DML..."); Thread.sleep(1000); // 模拟耗时操作 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { latch.countDown(); } }; Runnable task2 = () -> { try { // 执行DML操作 System.out.println("Thread 2 is executing DML..."); Thread.sleep(1500); // 模拟耗时操作 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { latch.countDown(); } }; executor.submit(task1); executor.submit(task2); try { // 等待所有线程完成DML操作 latch.await(); // 统一提交事务 System.out.println("All threads have completed DML, committing transaction..."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 回滚事务 System.out.println("An error occurred, rolling back transaction..."); } executor.shutdown(); } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值