專案場景:15萬條資料需要做邏輯處理,然后存入資料庫
硬體:windows 4核 i7 16G記憶體
問題描述:回應太慢,服務容易出現卡死
原因分析:
原先是JPA保存,每次與資料庫互動都會創建連接,執行完關閉連接,這樣是很耗時的
解決方案:
1.修改存庫方式,通過mybatis批量insert,一般每批3000條,陳述句過長會報錯,并不是每批量越大越好,需要根據實際情況分析,筆者這邊不做過多解釋,有興趣的可以看下相關知識
2.通過多執行緒執行
多執行緒配置
新建一個class,把以下組態檔直接原封不動copy過去就行,了解一下引數含義
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class ApplicationConfiguration {
/**
* 公共執行緒池
*/
@Bean
public ThreadPoolTaskExecutor commonThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor pool = new org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor();
int processNum = Runtime.getRuntime().availableProcessors(); // 回傳可用處理器的Java虛擬機的數量
int corePoolSize = (int) (processNum / (1 - 0.2));
int maxPoolSize = (int) (processNum / (1 - 0.5));
pool.setCorePoolSize(corePoolSize); // 核心池大小
pool.setMaxPoolSize(maxPoolSize); // 最大執行緒數
pool.setQueueCapacity(maxPoolSize * 1000); // 佇列程度
pool.setThreadPriority(Thread.MAX_PRIORITY);
pool.setDaemon(false);
pool.setKeepAliveSeconds(300);// 執行緒空閑時間
return pool;
}
}
實體呼叫
這里模擬一個保存方法
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // 注入執行緒池
@Autowired
private AggregateAccountingMapper aggregateAccountingMapper;
@Autowired
private AggregateAccountingService aggregateAccountingService;
@GetMapping("/save")
public void save() {
List<AggregateAccounting> list = this.aggregateAccountingService.list(); // 這里模擬15萬條資料源
// 注入執行緒池
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
threadPoolTaskExecutor);
/**
* partition()方法 大家可以看一下
* 例如 3001條資料 他會自動幫你分成兩個陣列 第一個陣列3000條 第二個陣列1條
* 不需要我們再像以前一樣 通過for回圈處理截取
*/
List<List<AggregateAccounting>> lists = Lists.partition(list, 3000);
lists.forEach(item -> {
// 這里做的事情就是 根據lists大小確認要多少個執行緒 給每個執行緒分配任務
completionService.submit(new Callable() {
@Override
public Object call() throws Exception {
// insertList()方法 就是批量insert陳述句
return aggregateAccountingMapper.insertList(item);
}
});
});
// 這里是讓多執行緒開始執行
lists.forEach(item -> {
try {
completionService.take().get();
} catch (InterruptedException | ExecutionException e) {
System.out.println(e);
}
});
}
}
總結
通過mybatis批量insert 15萬條資料(包含業務處理時間)
1.單執行緒:65S
2.多執行緒:50S
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289260.html
標籤:java
上一篇:Android的Kotlin匯入java專案后的AppCompatActivity父類紅標了
下一篇:Mybatis核心原理
