基于mybatisplus 的 java 异步储存队列

基于mybatisplus 的 java 异步储存队列
异步储存,减少与数据库之间的交互造成的堵塞使性能下降

import com.baomidou.mybatisplus.extension.service.IService;

import java.util.LinkedList;
import java.util.List;

/**
 * ClassName: MybatisSaveMQ
 * Description: 保存队列
 * date: 2021-03-19
 *
 * @since JDK 1.8
 */

public class MybatisSaveMQ<T> {

    private volatile List<T> list = new LinkedList<>();

    private volatile List<T> saveList ;

    private volatile List<T> cleanList = new LinkedList<>();

    private final IService<T> service;

    private final Class<T> clazz;

    private volatile int threadNum = 0;

    public MybatisSaveMQ(IService<T> service,Class<T> clazz){
        this.service = service;
        this.clazz = clazz;
    }

    public void save(T t){
        this.list.add(t);
        if(threadNum < 3){
            threadNum ++;
            new Thread(){
                @Override
                public void run() {
                    synchronized (clazz){
                        saveList = list;
                        list = cleanList;
                        service.saveBatch(saveList);
                        cleanList = saveList;
                        cleanList.clear();
                        threadNum --;
                    }
                }
            }.start();
        }
    }

}

下面的是线程优化过的,并且增加了异常处理。单独维护一个保存线程,工作线程负责将数据压入队列,保存线程负责将队列中数据存入数据库

import com.baomidou.mybatisplus.extension.service.IService;
import lombok.SneakyThrows;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ClassName: MybatisSaveMQ
 * Description: 保存队列
 * date: 2021-03-19
 *
 * @since JDK 1.8
 */

public class MybatisSaveMQ<T> {

    private volatile List<T> list = new LinkedList<>();

    private volatile List<T> saveList ;

    private volatile List<T> cleanList = new LinkedList<>();

    private final IService<T> service;

    private volatile int threadNum = 0;

    private Thread workTread ;

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

    public MybatisSaveMQ(IService<T> service){
        this.service = service;
        workTread = new Thread(){
            @SneakyThrows
            @Override
            public void run() {
                for (;;){
                    if(threadNum == 0){
                       lock.lock();
                       if(threadNum == 0){
                           condition.await();
                       }
                       lock.unlock();
                    }
                    saveList = list;
                    list = cleanList;
                    try {
                        service.saveBatch(saveList);
                    }catch (Exception e){
                        e.printStackTrace();
                        saveList.forEach(item ->{
                            try {
                                service.save(item);
                            }catch (Exception e1){
                                e1.printStackTrace();
                            }
                        });
                    }
                    cleanList = saveList;
                    cleanList.clear();
                    threadNum --;
                }
            }
        };
        workTread.start();
    }


    public void synchronized save(T t){
        this.list.add(t);
        if(threadNum < 2){
            threadNum ++;
            if(threadNum == 1){
                lock.lock();
                condition.signal();
                lock.unlock();
            }
        }
    }

}

该队列依靠所需工作线程数控制获取线程锁的逻辑,在高并发时没有线程锁的操作,两个线程几乎互不影响,没有性能损耗;
经测试,单纯的依靠mybatisPlus 原生save 方法逐条储存十万条数据到方法结束返回用时 1100多秒,同样的环境下,该队列将同样的数据压入队列并返回的时间为8毫秒,保存线程将数据批量存入数据库的时间为 32 秒

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值