借助CountDownLatch实现多线程事务回滚

1.CountDownLatch

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信。CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

2.多线程事务回滚

在使用多线程同时执行多个事务时,有时几个事务之间有着关联关系,即要么都成功要么都失败,在这种情况下,只是单纯的基于注解@Transactional是无法实现,因此当需要某个子线程事务失败了,其它相关的子线程也都需要回滚事务,下面用简单例子说明使用方式

直接上代码:实例代码用打印代替了实际的事务处理,注释写的很详细

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

public class Test {

    public static void main(String[] args) throws InterruptedException {

        // 主线程-数量就是相关联的子线程数
        CountDownLatch mainThreadLatch = new CountDownLatch(10);

        // 子线程-数量固定为 1
        // 这样所有子线程都会由同一个rollBackLatch等待
        // 然后在主线程里面只需rollBackLatch.countDown就可以同时放行所有子线程
        CountDownLatch rollBackLatch  = new CountDownLatch(1);

        // 线程执行标志
        // 用于标志是否有线程事务失败了
        // 默认没有全部成功,在子线程执行中遇到有失败的才将这个值设为 true
        AtomicBoolean rollbackFlag = new AtomicBoolean(false);

        // 创建 10个线程
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    // 用随机睡眠时间模拟业务处理
                    Thread.sleep((long) (Math.random() * 3000 + 1000));

                    System.err.println("线程:" + finalI + "执行完成,等其它线程结束待中...");

                    mainThreadLatch.countDown();
                    // 当前子线程等待其它线程结束
                    rollBackLatch.await();

                    if(rollbackFlag.get()) {
                        // 有失败的事务则当前事务回滚
                        System.err.println("有线程执行异常,将回滚事务,线程:" + finalI);
                    } else {
                        // 没有失败的事务则结束
                        System.err.println("线程:" + finalI + "执行完成!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

        // 主线程等待子线程结束
        mainThreadLatch.await();
        //所有等待的子线程全部放开
        rollBackLatch.countDown();

        if(rollbackFlag.get()){
            System.out.println("fail");
        }else{
            System.out.println("success");
        }
    }
}

没有失败事务的执行结果:

借助CountDownLatch实现多线程事务回滚_第1张图片

有失败的事务执行结果:

代码修改部分如下:(本次模拟是在第 8 个线程执行时将rollbackFlag设为 true)

// 用随机睡眠时间模拟业务处理
Thread.sleep((long) (Math.random() * 3000 + 1000));
if(finalI == 7) {
    rollbackFlag.set(true);
} else {
    System.err.println("线程:" + finalI + "执行完成,等其它线程结束待中...");
}

结果:

借助CountDownLatch实现多线程事务回滚_第2张图片

你可能感兴趣的:(java,jvm,开发语言)