TODO 网上关于 多线程的文章大多都是 2个线程直线的事务,3个线程开始事务,要自己编写,作者比较菜,写不清白线程的唤醒与休眠
void saveException() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句1").build();
service.save(vo);
int i = 1/0; //出现异常但是不会回滚
}, THREAD_POOL);
future.get(); //执行异步代码
UserVO vo = UserVO.builder().age(20).name("异常保存测试-不会执行语句").build();
service.save(vo);
}
void save02Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句1").build();
service.save(vo);
int i = 1/0; //出现异常但是不会回滚
}, THREAD_POOL);
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句2").build();
service.save(vo);
future.get(); //执行异步代码
}
@Test
@Transactional
void save02Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句1").build();
service.save(vo);
int i = 1/0; //出现异常但是不会回滚
}, THREAD_POOL);
UserVO vo = UserVO.builder().age(20).name("异常保存测试-异常后回滚").build();
service.save(vo);
future.get(); //执行异步代码
}
@Test
@Transactional
void save04Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句1").build();
service.save(vo);
}, THREAD_POOL);
UserVO vo = UserVO.builder().age(20).name("异常保存测试-异常后回滚").build();
service.save(vo);
future.get(); //执行异步代码
int i = 1/0; //异常点
}
@Test
@Transactional
void save03Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-会执行语句1").build();
service.save(vo);
int i = 1/0; //异常点
}, THREAD_POOL)
.exceptionally(throwable -> {
//捕获异常做处理 却不能回滚事务
log.error("捕获到异常");
return null;
});
UserVO vo = UserVO.builder().age(20).name("异常保存测试-异常后回滚").build();
service.save(vo);
future.get(); //执行异步代码
}
/**
* 主线程 1-1 子线程 事务回滚 PROPAGATION_REQUIRES_NEW
* 外层事务 未提交
* @throws Exception
*/
@Test
@Transactional(rollbackFor = Exception.class)
void save05Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//创建事务 内部事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = dataSourceTransactionManager.getTransaction(def);
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异步线程-回滚数据").build();
try {
service.save(vo);
int i = 1 / 0; //异常点
} catch (Exception e){
dataSourceTransactionManager.rollback(status);
throw new RuntimeException();
}
dataSourceTransactionManager.commit(status);
}, THREAD_POOL).exceptionally(
throwable->{
throw new RuntimeException("捕获线程内部异常,抛出");
});
UserVO vo = UserVO.builder().age(21).name("主线程-异常后回滚").build();
service.save(vo);
future.get(4,TimeUnit.SECONDS); //执行异步代码
}
/**
* 主线程异常 ,异步线程无法回滚
* @throws Exception
*/
@Test
//@Transactional(rollbackFor = Exception.class)
void save06Exception() throws Exception {
//外层事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus status = dataSourceTransactionManager.getTransaction(def);
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//创建事务 内部事务
DefaultTransactionDefinition defNei = new DefaultTransactionDefinition();
defNei.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(defNei);
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异步线程-回滚数据").build();
try {
service.save(vo);
//int i = 1 / 0; //异常点
}catch (Exception e){
dataSourceTransactionManager.rollback(transaction);
throw new RuntimeException("内存抛出异常");
}
dataSourceTransactionManager.commit(transaction);
}, THREAD_POOL).exceptionally(throwable -> {
throw new RuntimeException("内存抛出异常");
});
UserVO vo = UserVO.builder().age(21).name("主线程-异常后回滚").build();
service.save(vo);
int i = 1 / 0; //异常点
future.get(4,TimeUnit.SECONDS); //执行异步代码
boolean completedExceptionally = future.isCompletedExceptionally();
if(completedExceptionally){
throw new RuntimeException("主线程异常");
}
dataSourceTransactionManager.commit(status);//提交
}
意识到问题,是事务跟线程绑定,线程死亡,主线线程,无法操作子线程,作为思路,继续改写代码
/**
* 以get 为分解 回滚事务
* @throws Exception
*/
@Test
void save07Exception() throws Exception {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//外层事务
DefaultTransactionDefinition defNei = new DefaultTransactionDefinition();
defNei.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus statusNei = dataSourceTransactionManager.getTransaction(defNei);
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异常保存测试-数据会保存").build();
try {
service.save(vo);
//int i = 1/0; //出现异常 会回滚
}catch (Exception e){
dataSourceTransactionManager.rollback(statusNei);
throw new RuntimeException("抛出异常");
}
dataSourceTransactionManager.commit(statusNei);
}, THREAD_POOL);
//int i = 1/0; //出现异常 会回滚
Void unused = future.get();//执行异步代码 这行代码非常重要 关系到异常
int i = 1/0; //出现异常 回滚失效,应为异步线程已经在get时消亡了 (估计)
UserVO vo = UserVO.builder().age(20).name("异常保存测试-数据不会保存").build();
service.save(vo);
}
get之后 内部线程消亡,主线程,发生异常内部事务不会回滚
这里因该也可自己去写线程的,睡眠唤醒,来实现多个 任务之间的事务回滚。本人技术渣,写不明白。
/**
* 失败案例
* @throws Exception
*/
@Test
void save08Exception() throws Exception {
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
//外层事务
DefaultTransactionDefinition defNei = new DefaultTransactionDefinition();
defNei.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus statusNei = dataSourceTransactionManager.getTransaction(defNei);
//异常出现也会执行
UserVO vo = UserVO.builder().age(20).name("异步线程1-数据会保存").build();
try {
service.save(vo);
//int i = 1/0; //出现异常 会回滚 异步线程2 不会回滚
}catch (Exception e){
dataSourceTransactionManager.rollback(statusNei);
throw new RuntimeException("抛出异常");
}
dataSourceTransactionManager.commit(statusNei);
}, THREAD_POOL);
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
//外层事务
DefaultTransactionDefinition defNei = new DefaultTransactionDefinition();
defNei.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus statusNei = dataSourceTransactionManager.getTransaction(defNei);
//异常出现也会执行
UserVO vo = UserVO.builder().age(30).name("异步线程2-数据会保存").build();
try {
service.save(vo);
int i = 1/0; //出现异常 会回滚 异步线程1 不会回滚
}catch (Exception e){
dataSourceTransactionManager.rollback(statusNei);
throw new RuntimeException("抛出异常");
}
dataSourceTransactionManager.commit(statusNei);
}, THREAD_POOL);
//int i = 1/0; //出现异常 会回滚
Void unused = CompletableFuture.allOf(future1, future2).get();//执行异步代码 这行代码非常重要 关系到异常
//int i = 1/0; //出现异常 回滚失效,应为异步线程已经在get时消亡了 (估计)
UserVO vo = UserVO.builder().age(10).name("主线程-数据不会保存").build();
service.save(vo);
}
目前还无法正常使用