Implementation of Java Multithreaded Transaction Management
- 2021-10-25 06:58:38
- OfStack
1. Inherit the Thread class
2. Implement the Runnable interface
3. Implement the Callable and Future interfaces
Multithreaded single data transaction management
Today is to discuss "Java to achieve multithreaded single data transaction management", before that, by the way, I will review several ways to achieve multithreading
Three Ways to Realize Multithreading
1. Inherit the Thread class
The first method is to inherit the Thread class and override the run () method
public class TestThread extends Thread {
public void run() {
System.out.println(" Inheritance Thread Class, overriding the run Method ");
}
}
When used, new1 instances execute the start () method
TestThread testThread1 = new TestThread(); // New status
TestThread testThread2 = new TestThread(); // New status
testThread1.start(); // Ready status
testThread2.start(); // Ready status
When to execute depends on cpu scheduling
2. Implement the Runnable interface
Because of the characteristic of "single inheritance and multiple implementations" of Java, when we have already inherited one class, we can no longer inherit the Thread class. At this time, we can implement the run () method by implementing the Runnable interface
public class TestThread extends FatherClass implements Runnable {
public void run() {
System.out.println(" Realization Runnable Interface, implementation run Method ");
}
}
The Thread class also implements the Runnable interface
When using it, you need to instantiate one Thread first and pass in your own TestThread instance
TestThread testThread = new TestThread();
Thread thread = new Thread(testThread);
thread.start();
3. Implement Callable and Future interfaces
This method is different from the first two methods in that it can obtain the results of thread processing. Therefore, this method is suitable for scenarios where the results of threads need to be processed
class TestCallable implements Callable<Integer> {
@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;
}
}
When in use, first create TestCallable object, then use FutureTask to wrap MyCallable object, then use FutureTask object as target of Thread object to create a new thread, finally thread executes start () method, and the thread enters ready state
Callable<Integer> testCallable = new TestCallable(); // Create TestCallable Object
FutureTask<Integer> futureTask = new FutureTask<Integer>(testCallable); // Use FutureTask To wrap MyCallable Object
Thread thread = new Thread(futureTask); // FutureTask Object as a Thread Object's target Create a new thread
thread.start();
Multithreaded single data transaction management
We sometimes encounter such scenes: In order to update or insert a large number of data, it is necessary to open multi-threads to improve efficiency. It is also hoped that each thread can process each piece of data when processing one batch of data, and realize a single piece of data rollback instead of all data rollback when errors occur (all data rollback will be discussed later). Look at the code first:
According to the above multithreading knowledge, we first define a business thread class as follows:
public class TestTranstionalThread extends Thread {
private List<BalBankDictEntity> balBankDictEntities;
public TestTranstionalThread( List<BalBankDictEntity> balBankDictEntities){
this.balBankDictEntities = balBankDictEntities;
}
@Override
public void run() {
log.info(" Thread {} Begin ",Thread.currentThread().getName());
for (BalBankDictEntity balBankDictEntity : balBankDictEntities) {
try{
collBillDao.insOneBank(balBankDictEntity);
}catch (BusiException e){
log.error("{} Rollback ",balBankDictEntity.getBankId());
}
}
log.info(" Thread {} End ",Thread.currentThread().getName());
}
}
The insOneBank () method is as follows. Note that the @ Transactional annotation has a transaction isolation level of: REQUIRES_NEW, creating a new transaction.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insOneBank(BalBankDictEntity balBankDictEntity){
balBankDictMapper.insert(balBankDictEntity);
/* Simulate the occurrence of an exception, throw an exception, and realize the rollback of inserted data */
if (Integer.parseInt(balBankDictEntity.getBankId().substring(2)) % 100 == 0){
throw new BusiException("test");
}
}
Start multithreading for business processing, and pay attention to adding @ Transactional annotation
@Transactional
public void testTransactional(){
/* Analog test data */
List<BalBankDictEntity> balBankDictEntities = new ArrayList<>();
for (int i = 0 ; i < 100000 ; i ++){
BalBankDictEntity balBankDictEntity = new BalBankDictEntity();
balBankDictEntity.setBankCode("BK" + i);
balBankDictEntity.setBankId("ID" + i + "");
balBankDictEntity.setBankName("N" + i + "N");
balBankDictEntities.add(balBankDictEntity);
}
int totalNum = balBankDictEntities.size();
log.info("totalNum" + totalNum);
/* Points 10 Thread processing */
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
int dealNum = totalNum % 10 == 0 ? totalNum / 10 : totalNum / 10 + 1; // Calculate the amount of processing per thread
for (int i = 1; i <= 10 ; i++ ){
List<BalBankDictEntity> balBankDictEntityList = splitDataList(balBankDictEntities,dealNum,10,i); // Cutting data sets to achieve data isolation
TestTranstionalThread testTranstional = new TestTranstionalThread(balBankDictEntityList);
fixedThreadPool.execute(testTranstional);
}
}
Finally, multiple threads insert data concurrently, and the abnormal data is rolled back separately without affecting the whole