前言
- 之前遇到过一个面试题,要求的是在多线程执行同一批任务里,如果有有一个线程执行失败,那么需要把其他线程通知回滚任务。其实就是要么全部执行成功,要么全部执行失败。很明显这就相当于满足事务的原子性。
- 废话不多说,下面直接上代码。
代码实现
public class Test1 {
private static volatile Boolean SUBMIT = Boolean.TRUE;
public static void main (String[] args) {
int num = 5;
List<Boolean> childList = new ArrayList<>();
CountDownLatch PASS_COUNT = new CountDownLatch(num);
CountDownLatch NOTICE_COUNT = new CountDownLatch(1);
ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(num + 1, num + 1, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10));
for (int i = 0; i < num; i++) {
int ii = i;
EXECUTOR.execute(() -> {
try {
System.out.println(Thread.currentThread().getName() + ":开始执行");
if (ii == 2) {
}
childList.add(Boolean.TRUE);
Thread.sleep(10);
System.out.println(Thread.currentThread().getName() + ":可以准备提交数据,等待主线程响应");
PASS_COUNT.countDown();
NOTICE_COUNT.await();
if (SUBMIT) {
System.out.println(Thread.currentThread().getName() + ":提交数据成功");
} else {
System.out.println(Thread.currentThread().getName() + ":有线程异常,回滚提交");
}
} catch (Exception e) {
System.out.println(Thread.currentThread().getName() + ":我异常了");
childList.add(Boolean.FALSE);
PASS_COUNT.countDown();
}
});
}
try {
PASS_COUNT.await();
SUBMIT = childList.size() == num && childList.stream().allMatch(Boolean::booleanValue);
NOTICE_COUNT.countDown();
} catch (Exception e) {
}
}
}
---------------------------------------------------
结果:
pool-1-thread-1:开始执行
pool-1-thread-2:开始执行
pool-1-thread-3:开始执行
pool-1-thread-4:开始执行
pool-1-thread-5:开始执行
pool-1-thread-2:可以准备提交数据,等待主线程响应
pool-1-thread-1:可以准备提交数据,等待主线程响应
pool-1-thread-5:可以准备提交数据,等待主线程响应
pool-1-thread-3:可以准备提交数据,等待主线程响应
pool-1-thread-4:可以准备提交数据,等待主线程响应
pool-1-thread-2:提交数据成功
pool-1-thread-1:提交数据成功
pool-1-thread-5:提交数据成功
pool-1-thread-3:提交数据成功
pool-1-thread-4:提交数据成功
if (ii == 2) {
throw new Exception(Thread.currentThread().getName() + ":我异常了,哈哈");
}
------------------------------------------------------------
结果:
pool-1-thread-1:开始执行
pool-1-thread-2:开始执行
pool-1-thread-4:开始执行
pool-1-thread-3:开始执行
pool-1-thread-5:开始执行
pool-1-thread-3:我异常了
pool-1-thread-2:可以准备提交数据,等待主线程响应
pool-1-thread-1:可以准备提交数据,等待主线程响应
pool-1-thread-5:可以准备提交数据,等待主线程响应
pool-1-thread-4:可以准备提交数据,等待主线程响应
pool-1-thread-2:有线程异常,回滚提交
pool-1-thread-4:有线程异常,回滚提交
pool-1-thread-5:有线程异常,回滚提交
pool-1-thread-1:有线程异常,回滚提交
最后
- 如果把上述代码中的多个线程看做多个微服务,那就对分布式事务的2PC两阶段提交的实现了。
- 分布式事务里除了两阶段提交,还有3阶段提交(3PC) TCC XA Seata等等模式。如果有兴趣读者可以自行查看和实现。
参考文章