今年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
//END
boolean 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(){
.....;
}
}
。。。