多线程事务回滚
场景项目需要 导入一批数据,对数据进行切割,用多线程跑。问题点方法上增加@Transactional,对多线程无效,发生异常,子线程不会回滚,即使在子线程中增加@Transactional。原因:线程不归spring容器管理,也就不指望通知回滚了。上代码1.将大数据进行切割// apache自带切割api, num是对应想要切几段ListUtils.partition(list, num);2、使
·
场景
项目需要 导入一批数据,对数据进行切割,用多线程跑。
问题点
方法上增加@Transactional,对多线程无效,发生异常,子线程不会回滚,即使在子线程中增加@Transactional。
原因:线程不归spring容器管理,也就不指望通知回滚了。
上代码
1.将大数据进行切割
// apache自带切割api, num是对应想要切几段
ListUtils.partition(list, num);
2、使用异常标志、发令枪控制各线程回滚
@Transactional(rollbackFor = Exception.class)
public Result<String> dealData(int sheetMergeCount) {
// todo 业务逻辑...
// 切割数据
List<List<Integer>> list = splitList(sheetMergeCount, 10);
// 异常标志,AtomicBoolean保证线程安全
AtomicBoolean isError = new AtomicBoolean(false);
// 发令枪,长度是切割的子集合数量
CountDownLatch countDownLatch = new CountDownLatch(list.size());
for (List<Integer> integerList : list) {
// 将任务放进线程池
ThreadPoolUtil.exec(() -> {
// 将事务操作放在新的类中,并开启事务
extraService.upload(integerList, isError, countDownLatch);
});
}
try {
// 等所有线程都跑完,判断异常标识,有异常,进行主线程内回滚
countDownLatch.await();
if (isError.get()) {
// 手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return Result.fail("系统异常,稍后重试");
}
return Result.success("success");
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.error("dealData发令枪异常", e);
}
return Result.fail("系统异常,稍后重试");
}
@Service
@Slf4j
public class ExtraServiceImpl implements ExtraService {
@Override
@Transactional(rollbackFor = Exception.class)
public void uploadData(List<Integer> integerList, AtomicBoolean isError, CountDownLatch countDownLatch) {
try {
// todo 业务逻辑
} catch (Exception e) {
log.error("ExtraService.uploadData异常", e);
// 发生异常,进行标记
isError.set(true);
} finally {
// 发令枪倒计时
countDownLatch.countDown();
}
try {
// 等所有线程都跑完,判断异常标识,有异常,线程内进行回滚
countDownLatch.await();
if (isError.get()) {
// 手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
} catch (Exception e) {
log.error("ExtraService.uploadData发令枪异常", e);
// 手动回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
}
ok!!!希望能帮到您,麻烦点个赞
更多推荐
已为社区贡献3条内容
所有评论(0)