昨天在項目中有一個excel導表的操作,於是就想着用多線程插入數據。網上找了下mabayis多線程插入數據,看了很多都是配置的xml,但我不是很喜歡寫xml.....於是自己手寫了一個,代碼可能不是很優雅,但還是記錄一下.不多說,直接上代碼。
controller,和dao就不放了,
主要是service層
@Override
public int upload(Long paperId,List<InterviewProblem> interviewProblems) {
//面試卷加題
InterviewPaper interviewPaper = interviewPaperMapper.selectByPrimaryKey(paperId);
interviewPaper.setCount(interviewPaper.getCount()+interviewProblems.size());
interviewPaperMapper.updateByPrimaryKey(interviewPaper);
//寫入題庫
//開啓一個線程池,3個線程
ExecutorService executor = Executors.newFixedThreadPool(3);
//計數器,初始爲需要插入的數據集的條數
CountDownLatch countDownLatch = new CountDownLatch(interviewProblems.size());
int i=0;
//出現異常返回
final int[] flag = {0};
try{
//每條數據都寫進去
for(;i<interviewProblems.size();i++) {
int index = i;
executor.execute(() -> {
try{
//插入業務
InterviewProblem interviewProblem = interviewProblems.get(index);
interviewProblem.setId(idWorker.nextId()+"");
interviewProblem.setInterviewPaperId(paperId);
interviewProblemMapper.insert(interviewProblem);
}catch(Exception e){
//寫入日誌
log.error("第"+index+"條出錯 "+e.getMessage());
//修改異常標誌
flag[0] = 1;
throw new RuntimeException("第"+index+"條出錯 ");
}finally {
//計數器減一
countDownLatch.countDown();
}
});
}
//如果計數器不爲0,就等待,這個如果計數不正確,主線程就會先執行,相當於數據還沒有插完,就返回成功給前端.
countDownLatch.await();
}catch(Exception e){
}finally {
//關閉線程池
executor.shutdown();
}
//判斷是否異常
if(flag[0] == 1)
return 1;
else
return 0;
}
這裏的線程池也可以換成
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,5,1,TimeUnit.SECONDS,new LinkedBlockingQueue<>(3));
如果不瞭解多線程和lamda表達式..
用我抽取的模板就行
public static void main(String[] args) {
int dataSize = 10000;//數據的條數
int threadNumber = 10;//開啓的線程數
CountDownLatch countDownLatch = new CountDownLatch(dataSize);
int i=0;
ExecutorService executor = Executors.newFixedThreadPool(threadNumber);
//出現異常返回
final int[] flag = {0};
try{
for(;i<dataSize;i++) {
int index = i;
executor.execute(() -> {
try{
//你的業務邏輯
System.out.println("第"+index+"成功");
}catch(Exception e){
//寫入日誌
log.error("第"+index+"條出錯 "+e.getMessage());
flag[0] = 1;
throw new RuntimeException("第"+index+"條出錯 ");
}finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
}catch(Exception e){
}finally {
executor.shutdown();
}
System.out.println("完成了.");
}
控制檯打印結果
模板也看不懂的,實際上tkmybatis自帶一種多線程的mapper接口
1.需要在你的mapper接口上繼承,InsertListMapper
public interface InterviewProblemMapper extends Mapper<InterviewProblem>, InsertListMapper<InterviewProblem>, BaseMapper<InterviewProblem> {
}
2.調用即可
interviewProblemMapper.insertList(interviewProblems);
不過我覺得這種自帶的不能夠細粒度的控制,另外原生mybatis和mybatisPlus不確定是否有這種寫好的接口,但手寫多線程在多個orm框架上都適用.