使用多執行緒優化批量匯入的回顯功能
阿新 • • 發佈:2019-01-23
最近參與開發的專案有批量匯入資料的功能,匯入回顯的過程中需要做一些校驗,以確保匯入資料的正確性。如果匯入的資料特別多,校驗規則也特別多,那麼一條一條校驗的時間就會很長,影響系統使用。這個時候可以使用多執行緒來並行校驗。這裡記錄一下,以防忘掉。
一般要匯入的每一條資料的校驗都是相互獨立的,那麼讓幾條資料並行校驗不會影響其他資料。基於這個思想,使用多執行緒優化匯入。
筆者所在專案使用了SSM框架,程式碼實現是在service層(這裡只是基於本人的工作環境而這樣寫,如果不是這樣的環境,實現思想也是一樣的。)
實現如下:
(1)新建一個ImportServiceImpl.java類,裡面建立一個回顯方法ehcoImportInfo()方法,和一個內部類ThreadParallel,實現Callable介面(如果沒有返回值,也可以實現Runnable介面)。
public class ImportServiceImpl {
//內部類(執行緒類)
private class ThreadParallel implements Callable<Object>{
//內部類無參構造方法,如果需要傳遞引數來啟動執行緒,則定義相應的有參構造方法
public ThreadParallel() {
}
@Override
public Object call() throws Exception {
//具體的校驗程式碼放在這裡處理
return null;
}
//回顯方法
public void ehcoImportInfo() {
//這個方法裡面將呼叫內部類ThreadParallel
}
}
(2)在這個ehcoImportInfo方法中使用這個內部類。
public void ehcoImportInfo() {
int listSize = 3000; // 匯入3000條資料
// 根據匯入的資料量確定啟動執行緒的個數(根據實際情況來確定)
int threadNum = 0; // 記錄執行緒數量
if (listSize > 0 && listSize < 100) {
threadNum = 1;
} else {
if (listSize >= 1000 && listSize <= 3000) {
threadNum = 10;
} else {
if ((listSize % 100) == 0) {
threadNum = listSize / 100;
} else {
threadNum = listSize / 100 + 1;
}
}
}
List<Object> subList; // 存放一個範圍內的匯入資料
int count =1; // 行號
// 存放所有分割的資料
Map<Integer, Object> map = new HashMap<Integer, Object>();
// 分割匯入的資料
for (int i = 0; i < threadNum; i++) {
subList= new ArrayList<Object>();
for (int j = (listSize/threadNum)*(count-1); j < (listSize/threadNum)*count; j++) {
mList.add(list.get(j));
}
map.put(i, mList);
count ++;
}
// 存放執行緒返回值
List<Future> futureList = new ArrayList<Future>();
ExecutorService executorService = Executors.newFixedThreadPool(threadNum); // 建立執行緒池
// 建立執行緒,並啟動執行緒(這是關鍵,這裡面建立了內部執行緒類的物件,裡面傳的引數,根據實際情況決定,相應的內部類中也要有對應的構造方法。利用submit可以啟動執行緒,)
for (int x = 0; x < map.size(); x++) {
futureList.add(executorService.submit(new ThreadParallel(map.get(x),(listSize/threadNum)*x + 1)));
}
executorService.shutdown(); // 關閉執行緒池
// 拼接提示資訊
for (Future future : futureList) {
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
這只是大致的結構,程式碼並不完整,主要是理解這種思想和做法。總結一下:就是在方法中使用內部執行緒類,將大批量資料劃分成小批量資料,然後每一個小批量資料啟用一個執行緒並行執行,然後再彙總結果(不需要返回值的就不用處理結果了),這樣可以成倍地降低校驗時間。