表中有50W笔数据,表结构很简单,主键id(32位随机码),外加一个name字段,都是varchar2类型,想取出全部数据并封装到JavaBean中,但是一次查询耗时太长,想使用多线程的方法取出这些数据,但是用下面的多线程代码运行后发现,预期能取出全部50W笔,但是实际只取出499992笔,少了8笔,不知道是什么原因。
思路是先创建容量为50W的公共List,把这个List当类成员变量传递到线程对象里,然后创建100个线程,每个线程单独创建数据库连接执行查询,然后把各自查出来的结果集封装到JavaBean然后填充到公共list中,代码如下:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class Test2 {
public static void main(String[] args) {
Test2 t2 = new Test2();
List list_db = t2.getAll();
}
public List getAll(){
//Connection conn = null;
List list_db = new ArrayList(500000);
try{
long start = System.currentTimeMillis();
//Class.forName(DRIVER_CLASSNAME);
//conn = DriverManager.getConnection(URL, USER, PASSWORD);
QueryThread qt = null;
for(int i = 0; i < 100; i++){
qt = new QueryThread();
//qt.setConn(conn);
qt.setList_db(list_db);
qt.settName("thread" + i);
qt.setStart((i*5000+1));
qt.setEnd((i+1) * 5000);
Thread dao = new Thread(qt);
dao.start();
}
while(true){
if(list_db.size() == 500000){
break;
}
System.out.println("..." + list_db.size());
Thread.sleep(1000);
}
long end = System.currentTimeMillis();
System.out.println("封装完毕!耗时:" + (end - start)/1000 + "秒!");
System.out.println("查询完成,结果集:" + list_db.size());
}catch(Exception e){
e.printStackTrace();
}finally{
//if(conn != null){
//try {
//conn.close();
//} catch (SQLException e) {
//e.printStackTrace();
//}
//}
}
return list_db;
}
}
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public class QueryThread extends Thread{
public static String DRIVER_CLASSNAME = "x";
public static String URL = "x";
public static String USER = "x";
public static String PASSWORD = "x";
private List list_db;
public void setList_db(List list_db) {
this.list_db = list_db;
}
private int start;
private int end;
public void setStart(int start) {
this.start = start;
}
public void setEnd(int end) {
this.end = end;
}
private String tName;
public void settName(String tName) {
this.tName = tName;
}
@Override
public void run(){
Connection conn = null;
PreparedStatement stmt = null;
try{
System.out.println("线程[" + this.tName + "]开始执行!");
Class.forName(DRIVER_CLASSNAME);
conn = DriverManager.getConnection(URL, USER, PASSWORD);
stmt = conn.prepareStatement("select t2.* from (select t1.*,rownum rn from (select * from testa t order by t.taid) t1 where rownum <= ?) t2 where t2.rn >= ? ");
stmt.setInt(1, end);
stmt.setInt(2, start);
ResultSet rs = stmt.executeQuery();
A a = null;
int count = 0;
while(rs.next()){
a = new A();
a.settId(rs.getString(1));
a.setaName(rs.getString(2));
this.list_db.add(a);
count++;
//System.out.println("线程[" + this.tName + "] 遍历中结果集:" + this.list_db.size());
}
System.out.println("线程[" + this.tName + "]执行结束! 结果集:" + count);
}catch(Exception e){
System.out.println("线程[" + this.tName + "]插入失败!" + e.getMessage());
e.printStackTrace();
}finally{
if(stmt != null){
try {
stmt.close();
} catch (SQLException e2) {
System.out.println("线程[" + this.tName + "]关闭stmt 失败!" + e2.getMessage());
e2.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
问题补充:100个线程每个线程查询5000笔,用分页和动态传参的方式实现