Java多线程事务管理的实现

本文主要介绍了Java多线程事务管理的实现,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

今天要讨论的是“Java实现多线程单条数据事务管理”,在此之前,顺便回顾一下实现多线程的几种方式

实现多线程的三种方式

一、继承Thread类

第一种方法是继承Thread类,重写run()方法

 public class TestThread extends Thread {   public void run() {    System.out.println("继承Thread类,重写run方法");   } } 

使用时,new一个实例,执行start()方法

 TestThread testThread1 = new TestThread(); // 新建状态 TestThread testThread2 = new TestThread(); // 新建状态 testThread1.start(); // 就绪状态 testThread2.start(); // 就绪状态 

何时执行取决于cpu调度

二、实现Runnable接口

因为Java“单继承、多实现”的特性,当我们已经继承了一个类的时候,则无法再继承Thread类,此时可以通过实现Runnable接口的方式,实现run()方法

 public class TestThread extends FatherClass implements Runnable {   public void run() {    System.out.println("实现Runnable接口的方式,实现run方法");   } } 

Thread类也是实现Runnable接口

使用时,需要首先实例化一个Thread,并传入自己的TestThread实例

 TestThread testThread = new TestThread(); Thread thread = new Thread(testThread); thread.start(); 

三、实现Callable和Future接口

该方法区别于前两种的特点是:能够获得线程处理的结果。因此该方式适用于需要对线程的结果进行处理的场景

 class TestCallable implements Callable { @Override public Integer call() { int sum = 0; for (int i = 0; i <100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); sum += i; } return sum; } }

使用时,先创建TestCallable对象,然后使用FutureTask来包装MyCallable对象,再将FutureTask对象作为Thread对象的target创建新的线程,最后thread执行start()方法,线程进入就绪状态

 Callable testCallable = new TestCallable();                    // 创建TestCallable对象 FutureTask futureTask = new FutureTask(testCallable); // 使用FutureTask来包装MyCallable对象 Thread thread = new Thread(futureTask);                                 // FutureTask对象作为Thread对象的target创建新的线程 thread.start(); 

多线程单条数据事务管理

我们有时会遇到这样的场景:要对大批量的数据进行更新或插入操作,需要开启多线程来提高效率,又希望每个线程在的处理一批数据时,能够对其中每条数据进行处理的时,做到出错时实现单条数据回滚,而不是所有数回滚(所有数据回滚后续讨论)。先看代码:

根据以上多线程知识,我们先定义一个业务线程类如下:

 public class TestTranstionalThread extends Thread { private List balBankDictEntities; public TestTranstionalThread( List balBankDictEntities){ this.balBankDictEntities = balBankDictEntities; } @Override public void run() { log.info("线程{}开始",Thread.currentThread().getName()); for (BalBankDictEntity balBankDictEntity : balBankDictEntities) { try{ collBillDao.insOneBank(balBankDictEntity); }catch (BusiException e){ log.error("{}回滚",balBankDictEntity.getBankId()); } } log.info("线程{}结束",Thread.currentThread().getName()); } }

insOneBank()方法如下,注意的@Transactional注解的事务隔离等级为:REQUIRES_NEW,创建一个新的事务。

 @Transactional(propagation = Propagation.REQUIRES_NEW) public void insOneBank(BalBankDictEntity balBankDictEntity){ balBankDictMapper.insert(balBankDictEntity); /* 模拟发生异常,抛出异常,实现将已插入数据回滚 */ if (Integer.parseInt(balBankDictEntity.getBankId().substring(2)) % 100 == 0){ throw new BusiException("test"); } }

开启多线程进行业务处理,注意加上@Transactional注解

 @Transactional public void testTransactional(){ /* 模拟测试数据 */ List balBankDictEntities = new ArrayList<>(); for (int i = 0 ; i <100000 ; i ++){ balbankdictentity new balbankdictentity(); balbankdictentity.setbankcode("bk" + i); balbankdictentity.setbankid("id" ""); balbankdictentity.setbankname("n" "n"); balbankdictentities.add(balbankdictentity); } int totalnum=balBankDictEntities.size(); log.info("totalnum" totalnum);> balBankDictEntityList = splitDataList(balBankDictEntities,dealNum,10,i);  // 切割数据集实现数据隔离 TestTranstionalThread testTranstional = new TestTranstionalThread(balBankDictEntityList); fixedThreadPool.execute(testTranstional); } }

最终实现多个线程并发插入数据,有异常的数据的单独回滚,不影响整体

以上就是Java多线程事务管理的实现的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java