使用ForkJoin对大量数据入库

废话不多说,直接上代码

实体类
package Test.TestDemo.Control.model;

/**
 * @auther 14
 * @date 2020/12/3 0003 - 16:15
 */
public class User {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public User(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public User() {
        super();
    }
}

package Test.TestDemo.Control.多线程.ForkJoin;

import Test.TestDemo.Control.model.User;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 利用ForkJoin拆分任务将大量数据分批入库
 * @author dang14
 * @create 2022/5/19 21:19
 *
 * ForkJoin是把大任务拆分成小任务,并行执行任务,提高效率,大数据量的时候使用
 * 特点:工作窃取
 * 这个里面维护的都是双端队列,一端队列执行完可以窃取另一端队列的任务来帮忙执行
 *
 *
 * 这边继承RecursiveAction接口,也可继承RecursiveTask接口。它们的区别是一个有返回值,一个没返回值。这里使用的是没有返回值的
 * 根据临界值判断是否要拆分任务
 * 如果需要拆分任务,按照拆分规则进行拆分
 * 拆分的任务通过递归再次进行拆分,一直到临界值为止
 * 拆分后的任务压入线程队列最后执行任务
 *
 */
public class ForkJoinInsertEntity extends RecursiveAction {

    //创建临界值。也就是任务粒度
    private static final int THRESHOLD = 10;
    //要插入的数据实体
    private List<User> userList;
    //Mapper实现类
    private UserMapper userMapper;

    //有参构造
    public ForkJoinInsertEntity(List<User> userList, UserMapper userMapper) {
        this.userList = userList;
        this.userMapper = userMapper;
    }

    @Override
    protected void compute() {
        boolean compute = userList.size() <= THRESHOLD;
        if(compute){
            userMapper.saveBatch(userList);
        }else{
            List<List<User>> lists = averageAssign(userList, 2);
            //递归分组
            ForkJoinInsertEntity task1 = new ForkJoinInsertEntity(lists.get(0), userMapper);
            ForkJoinInsertEntity task2 = new ForkJoinInsertEntity(lists.get(1), userMapper);
            //拆分的任务压入线程队列执行
            invokeAll(task1,task2);
        }
    }


    /**
     * 将一组数据平均分成N组
     * @param source   要分组的数据
     * @param n        分成几组
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> averageAssign(List<T> source, int n) {
        List<List<T>> result = new ArrayList<>();
        int remainder = source.size() % n;  //(先计算出余数)
        int number = source.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value;
            if (remainder > 0) {
                value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
                remainder--;
                offset++;
            } else {
                value = source.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        UserMapper userMapper = null;
        LinkedList<User> userLinkedList = new LinkedList<>();
        for (int i = 0; i < 1000; i++) {
            User user = new User();
            user.setId(i);
            user.setAge(i);
            user.setName("task:"+i);
            userLinkedList.add(user);
        }
        ForkJoinPool forkJoinPool = new ForkJoinPool(10);
        try {
            ForkJoinInsertEntity forkJoinInsertEntity = new ForkJoinInsertEntity(userLinkedList,userMapper);
            ForkJoinTask<Void> submit = forkJoinPool.submit(forkJoinInsertEntity);
            submit.get();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            forkJoinPool.shutdown();
        }

    }


}

完结!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值