Implementation of Java Multithreaded Transaction Management

  • 2021-10-25 06:58:38
  • OfStack

Three Ways to Realize Multithreading in Directory
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


Related articles: