1. 程式人生 > >使用多執行緒優化批量匯入的回顯功能

使用多執行緒優化批量匯入的回顯功能

最近參與開發的專案有批量匯入資料的功能,匯入回顯的過程中需要做一些校驗,以確保匯入資料的正確性。如果匯入的資料特別多,校驗規則也特別多,那麼一條一條校驗的時間就會很長,影響系統使用。這個時候可以使用多執行緒來並行校驗。這裡記錄一下,以防忘掉。

一般要匯入的每一條資料的校驗都是相互獨立的,那麼讓幾條資料並行校驗不會影響其他資料。基於這個思想,使用多執行緒優化匯入。

筆者所在專案使用了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(); } } }

這只是大致的結構,程式碼並不完整,主要是理解這種思想和做法。總結一下:就是在方法中使用內部執行緒類,將大批量資料劃分成小批量資料,然後每一個小批量資料啟用一個執行緒並行執行,然後再彙總結果(不需要返回值的就不用處理結果了),這樣可以成倍地降低校驗時間。