1. 程式人生 > 其它 >SpringBoot使用多執行緒方式插入資料到資料庫

SpringBoot使用多執行緒方式插入資料到資料庫

技術標籤:javamysqljava後端mysql

SpringBoot使用多執行緒方式插入資料到資料庫

1.自定義執行緒配置

@Configuration
@EnableAsync
public class ExecutorConfig {

    @Bean
    public Executor asyncServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心執行緒數
        executor.setCorePoolSize(2);
        //配置最大執行緒數
        executor.setMaxPoolSize(4);
        //配置佇列大小
        executor.setQueueCapacity(400);
        //配置執行緒池中的執行緒的名稱字首
        executor.setThreadNamePrefix("thread-");
        //拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //執行初始化
        executor.initialize();
        return executor;
    }

}

2.service層程式碼

 @Override
    @Async("asyncServiceExecutor")
    public void add(List<ZksyUnitConversion> conversionList) {
        conversionService.saveBatch(conversionList);
    }

@Async(“asyncServiceExecutor”)重要註解 引數為自定義執行緒的方法名
這層程式碼相當於就是你的執行緒執行的任務
3.呼叫執行緒在controller

@PostMapping("/add3")
    public boolean addConversion3(){
        ArrayList<ZksyUnit> list = new ArrayList<>();
        ArrayList<ZksyUnit> anoList = new ArrayList<>();
        ArrayList<ZksyUnitConversion> conversionList = new ArrayList<>();
        for (int i = 0; i < 20000; i++) {
            ZksyUnit zksyUnit = new ZksyUnit();
            zksyUnit.setId(i);
            zksyUnit.setUName("list"+i);
            zksyUnit.setCode("2021="+i);
            zksyUnit.setUpdateName("you"+i);
            zksyUnit.setCreateName("me"+i);
            list.add(zksyUnit);
        }
        for (int j = 0; j < 20; j++) {
            ZksyUnit zksyUnit = new ZksyUnit();
            zksyUnit.setId(j);
            zksyUnit.setUName("anoList"+j);
            zksyUnit.setCode("2021="+j);
            zksyUnit.setUpdateName("you"+j);
            zksyUnit.setCreateName("me"+j);
            anoList.add(zksyUnit);
        }
        for (ZksyUnit zksyUnit : anoList) {
            for (ZksyUnit unit : list) {
                ZksyUnitConversion zksyUnitConversion = new ZksyUnitConversion();
                zksyUnitConversion.setBasicCode(zksyUnit.getId());
                zksyUnitConversion.setTarget(unit.getId());
                zksyUnitConversion.setGroupName("group"+zksyUnit.getId());
                zksyUnitConversion.setUpdateName("111");
                zksyUnitConversion.setCreateName("222");
                conversionList.add(zksyUnitConversion);
                //boolean save = conversionService.save(zksyUnitConversion);
            }
        }
        try {
            int listSize=conversionList.size();
            int toIndex=OPENID_PHONE_NUM;
            for(int i = 0;i<conversionList.size();i+=OPENID_PHONE_NUM){
                if(i+OPENID_PHONE_NUM>listSize){//作用為toIndex最後沒有800條資料則剩餘幾條newList中就裝幾條
                    toIndex=listSize-i;
                }
                List<ZksyUnitConversion> newPMeSendToPhoneInfo = conversionList.subList(i,i+toIndex);
                //批量插入
                //            pMeSendToPhoneMapper.batchInsertPMePhoneData(newPMeSendToPhoneInfo);
                //conversionService.saveBatch(newPMeSendToPhoneInfo);
                asyncService.add(newPMeSendToPhoneInfo);
            }
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            //匯入完後減1
            countDownLatch.countDown();
        }
        return  true;
    }

private final CountDownLatch countDownLatch = new CountDownLatch(10);
這個引數是一個計數器 引數一般為你請求的數量他的作用是讓你的執行緒阻塞在那裡
加入countDownLatch.await();這個方法意思就是需要你多執行緒呼叫執行完畢之後才會執行你主執行緒的邏輯。只有當countDownLatch為0時,才不會阻塞。所以需要每執行一次,計數器countDownLatch減1.