今年3月份測試了一段代碼,資料庫中有300萬條資料,抽出處理後寫入檔案中。
大規模資料執行時,希望24小時內執行完畢,但是實際測試中,時間達到了27個小時之多。
---------------------------
---------------------------
今天又看到了這段代碼,發現他們應該已經解決了這個問題。
他們解決的方式是才有多線程進行處理。(以下的①,②,③ 三大塊)
好處
不但可以提高速度,當有檔案出力時,還可以減輕每個檔案的大小。
根據每條資料內容多少的不同,有時300萬達到400多M,
但有時,400萬條資料會達到1.2G之多。
當你的資料量時1.2G的檔案時,你的機器不好,就很難開啟這個檔案。
使用多線程時,會產生多個檔案,這樣每個檔案的大小也相應的減小。
(使用sakura,400M的檔案開啟,現在的機器HP OPTIPLEX 780是沒有問題的,
但是1.2G的檔案就無法開啟。)
①整體的處理流程
ResultSet userInfoList = getUserInfoList();// 建立一個資料池,這個資料池取出資料時是同步的。// 也就是是說,10個線程都從這裡取出資料,// 但是,在同一時刻,只能有一個線程取資料。 UserInfoSetPool userInfoSet = new UserInfoSetPool(userInfoList);List<Thread> threadList = new ArrayList<Thread>();List<BT001Thread> threadList = new ArrayList<BT001Thread>();for(int i=0, i<10, i++ ){ BT001Thread thread = new BT001Thread(fileDir, FileName + i ); logicThreadList.add(thread); Thread th = new(thread); // 具體的業務處理,線上程類的run方法中進行處理。 // 以為這些業務處理涉及到一些DB,檔案讀寫操作,浪費時間。 // 分成多線程來執行,就快多了! th.start(); threadList.add(th);}//NEXT//ERROR //ENDboolean runFlag = true;// 不斷檢查處理中線程的狀態。 while(runFlag){ int i = 0; for(TestThread thread : logicThreadList){ if(ERROR) { ....; } else if (NEXT){ break; } else if (END) { i++; } if( i >= 10 ){ // 十個線程都結束了,表明資料已經處理完畢。 runFlag = false; } }}for(Thread thread:threadList){ // 結束所有的線程。 thread.join();}
②供多個線程使用的資料池
UserInfoSetPool
public class UserInfoSetPool { ResultSet userInfoList ; public UserInfoSetPool(ArrayList userInfoList){ this.userInfoList = userInfoList; } /** * 使線程間能同步從資料池中取得資料。 */ public synchronized Map getUserInfo(){ Map<String, String> userInfo = null; if(userInfoList.hasNext()){ userInfo = new HashMap<String, String>(); userInfo.put("userId",userInfoList.get("user_id")); .... } return userInfo; }}
③線程類,從資料池中讀取資料,對每天資料進行相應的業務處理。
(真正的業務處理就在這裡!!)
BT001Thread
public class BT001 extends Thread { public String STATUS_ERROR = "ERROR"; public String STATUS_NEXT = "NEXT"; public String STATUS_END = "END"; // 資料池 public UserInfoSetPool userInfoSetPool = null; /** * 構造方法,初始化資料池 */ public BT0001(UserInfoSetPool userInfoSetPool, String fileDir, String fileName) { this.userInfoSetPool = userInfoSetPool; } /** * 線程的run方法 */ public void run() { status = NEXT; try{ boolean loopFlag = true; //讓線程一直執行下去. while(loopFlag){ // 從資料池中擷取資料。 Map userInfo = userInfoSetPool.getUserInfo(); if(userInfo ==null ) { loopFlag = false; } else { .....//業務處理 } }// end while status = END; } catch(){ status = ERROR; } } /** * 取得線程的狀態 */ public getThreadStatus(){ .....; } }
。。。