Java多个事务并发执行的一个面试题

现在有10个任务,每个任务需要执行10s,用线程池并发处理,每个线程会插入数据,需求:只要有一个线程插入数据失败了,其他所有线程的数据都需要回滚。

这个是并发事务的问题,也可以说是一个分布式事务的问题,解决方案不少,这里基于一种两阶段提交的方式进行处理。

即这里主线程作为事务协调者,多个线程作为参与者,直到多个参与者全部执行了事务操作后会给协调者返回执行结果,在此期间协调者会一直阻塞,同时,参与者也会阻塞直到协调者收到所有参与者的执行结果,只有有一个参与者执行失败,协调者就会通知所有参与者都进行回滚操作,反之则提交事务。

代码如下:

建表语句:

create table `abc` (
	`age` int (11)
); 

Mapper接口


public interface AbcMapper {

    @Insert("insert into abc values (#{val})")
    int insert(@Param("val")Object val);
}

测试类

 
public class MapperTest {

    @Autowired
    private AbcMapper abcMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    private CountDownLatch countDownLatch = new CountDownLatch(10);

    private final Object lock = new Object();

    private volatile boolean commit = true;

    @Test
    public void tes() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        for (int i = 1; i <= 10; i++) {
            int a = i;
            executorService.execute(() -> {
                Object value = a == 10 ? "a" : a;
                //Object value = a ;
                insert(value);
            });
        }
        countDownLatch.await();
        synchronized (lock){
            lock.notifyAll();
        }
    }

    private void insert(Object value) {
        TransactionStatus txStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            abcMapper.insert(value);
            TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
            countDownLatch.countDown();
        } catch (Exception e) {
            countDownLatch.countDown();
            commit = false;
            System.out.println(Thread.currentThread().getName() + "->error");
        }
        synchronized (lock) {
            try {
                System.out.println(Thread.currentThread().getName()+"->wait");
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"->do");
        System.out.println("commit:"+commit);
        if (commit) {
            transactionManager.commit(txStatus);
            System.out.println(Thread.currentThread().getName() + "->commit");
            return;
        }
        try {
            transactionManager.rollback(txStatus);
        }catch (Exception e){
            System.out.println("exception:"+e.getLocalizedMessage());
        }
        System.out.println(Thread.currentThread().getName() + "->rollback");
    }
}


执行结果如下:

pool-4-thread-10->error
pool-4-thread-10->wait
pool-4-thread-8->wait
pool-4-thread-2->wait
pool-4-thread-6->wait
pool-4-thread-5->wait
pool-4-thread-9->wait
pool-4-thread-1->wait
pool-4-thread-4->wait
pool-4-thread-3->wait
pool-4-thread-7->wait
pool-4-thread-7->do
pool-4-thread-3->do
commit:false
pool-4-thread-5->do
pool-4-thread-2->do
commit:false
pool-4-thread-1->do
commit:false
pool-4-thread-10->do
pool-4-thread-4->do
commit:false
pool-4-thread-6->do
commit:false
pool-4-thread-8->do
commit:false
pool-4-thread-9->do
commit:false
commit:false
commit:false
commit:false
pool-4-thread-10->rollback
pool-4-thread-1->rollback
pool-4-thread-5->rollback
pool-4-thread-6->rollback
pool-4-thread-2->rollback
pool-4-thread-8->rollback
pool-4-thread-4->rollback
pool-4-thread-7->rollback
pool-4-thread-9->rollback
pool-4-thread-3->rollback
 

所有的事务已经全部回滚,表中没有添加数据

展开阅读全文

页面更新:2024-02-23

标签:表语   事务   分布式   参与者   线程   主线   接口   解决方案   阶段   需求   操作   代码   方式   通知   数据   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top