Java – spring cannot propagate transactions to the recursive action of forkjoin

I am trying to implement a multithreading solution so that I can parallelize my business logic, including reading and writing to the database

Technology stack: Spring 4.0 2,Hibernate 4.3. eight

Here are some codes to discuss:

configuration

@Configuration
public class PartitionersConfig {

    @Bean
    public ForkJoinPoolfactorybean forkJoinPoolfactorybean() {
        final ForkJoinPoolfactorybean poolFactory = new ForkJoinPoolfactorybean();
        return poolFactory;
    }
}

service

@Service
@Transactional
public class MyService {

    @Autowired
    private OtherService otherService;

    @Autowired
    private ForkJoinPool forkJoinPool;

    @Autowired
    private MyDao myDao;

    public void performPartitionedActionOnIds() {
        final ArrayList<UUID> ids = otherService.getIds();

        MyIdPartitioner task = new MyIdsPartitioner(ids,myDao,ids.size() - 1);
        forkJoinPool.invoke(task);
    }
}

Repository / Dao

@Repository
@Transactional(propagation = Propagation.MANDATORY)
public class IdsDao {

    public MyData getData(List<UUID> list) {
        // ... 
    }
}

RecursiveAction

public class MyIdsPartitioner extends RecursiveAction {

    private static final long serialVersionUID = 1L;
    private static final int THRESHOLD = 100;

    private ArrayList<UUID> ids;
    private int fromIndex;
    private int toIndex;

    private MyDao myDao;

    public MyIdsPartitioner(ArrayList<UUID> ids,MyDao myDao,int fromIndex,int toIndex) {
        this.ids = ids;
        this.fromIndex = fromIndex;
        this.toIndex = toIndex;
        this.myDao = myDao;
    }

    @Override
    protected void compute() {
        if (computationSetIsSamllEnough()) {
            computeDirectly();
        } else {
            int leftToIndex = fromIndex + (toIndex - fromIndex) / 2;
            MyIdsPartitioner leftPartitioner = new MyIdsPartitioner(ids,fromIndex,leftToIndex);
            MyIdsPartitioner rightPartitioner = new MyIdsPartitioner(ids,leftToIndex + 1,toIndex);

            invokeAll(leftPartitioner,rightPartitioner);
        }
    }

    private boolean computationSetIsSamllEnough() {
        return (toIndex - fromIndex) < THRESHOLD;
    }

    private void computeDirectly() {
        final List<UUID> subList = ids.subList(fromIndex,toIndex);
        final MyData myData = myDao.getData(sublist);
        modifyTheData(myData);
    }

    private void modifyTheData(MyData myData) {
        // ...
        // write to DB
    }
}

After doing this, I get:

I understand that this is perfectly normal because transactions do not propagate through different threads Therefore, one solution is to manually create a transaction in each thread as proposed in another similar question But it's not satisfactory for me, so I've been searching

I found a discussion on the topic in the spring forum I found a very interesting paragraph:

Therefore, the first question arises: is it worth simplifying the read / write of the database, and will it really damage the consistency of the database? If the above reference is incorrect, I doubt whether there is a way to achieve the following purposes: myidpartitioner will be managed by spring - using @ scope ("prototype") - and passing the required parameters for recursive calls, so that transaction management can be left to spring?

Solution

It should be possible to use atomikos( http://www.atomikos.com )You can also choose to use nested transactions

If you do so, if multiple threads of the same root transaction write to the same table in the database, please pay attention to avoid deadlock

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>