我有一个带有1600多个记录的数据库,读取所有记录看起来很慢,所以我有了一个使用2个线程来获取数据的想法。我具有以下功能,但感觉不快...
private ArrayList<Worker> getWorkersOnMultipleThread() throws InterruptedException {
ArrayList<Worker> totalWorkers = new ArrayList<>();
ArrayList<Worker> totalWorkers2 = new ArrayList<>();
int total = db.getNumberOfWorkers();
int firstHalf, secondHalf;
firstHalf = total / 2;
if (total % 2 == 1) {
secondHalf = total / 2 + 1;
} else {
secondHalf = total / 2;
}
Thread t1 = new Thread() {
@Override
public void run() {
ArrayList<Worker> w1 = db.getHalfOfTheWorkers(firstHalf, true);
totalWorkers.addAll(w1);
}
};
Thread t2 = new Thread() {
@Override
public void run() {
ArrayList<Worker> w2 = db.getHalfOfTheWorkers(secondHalf, false);
totalWorkers2.addAll(w2);
}
};
t1.start();
t1.join();
t2.start();
t2.join();
totalWorkers.addAll(totalWorkers2);
return totalWorkers;
}
@Override
public ArrayList<Worker> getHalfOfTheWorkers(int limit, Boolean firstHalf) {
String sql;
ArrayList<Worker> workers = new ArrayList<>();
if (firstHalf) {
sql = "SELECT * FROM NAMES ORDER BY ID FETCH NEXT " + limit + " ROWS ONLY";
} else {
sql = "SELECT * FROM NAMES ORDER BY ID OFFSET " + limit + " ROWS";
}
try {
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
String name = rs.getString("name");
int id = rs.getInt("id");
workers.add(new Worker(id, name));
}
} catch (Exception ex) {
}
return workers;
}
我的想法是在第一个线程上获取前50%的记录,然后在第二个线程上获取后50%的记录,希望有一半的时间需要获取所有记录。它似乎不起作用(我的意思是它没有错误和内容,并且具有相同的速度...)
主要:
@Override
public void initialize(URL url, ResourceBundle rb) {
ArrayList<Worker> totalWorkers = new ArrayList<>();
try {
totalWorkers = getWorkersOnMultipleThread();
System.out.println(totalWorkers.size());
} catch (InterruptedException ex) {
Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
答案 0 :(得分:1)
之所以发生这种情况,是因为您是按顺序启动线程的,也就是说,t1
启动时,main处于使用t1.join()
的等待状态。在t2
线程完成执行之前,不会启动t1
线程。
t1.start();
t1.join(); //main waiting
t2.start();
t2.join();
因此您需要更改顺序:
t1.start();
t2.start();
t1.join(); //main waiting
t2.join();
这样,线程t1
和t2
将同时启动,并且您将指示main等待t1
和t2
都完成执行。
理想情况下,statement
对象不应在线程之间共享。您应该从线程池中为每个线程获取一个Connection
对象。
由于您使用的是Apache derby,因此请参见开发人员指南discourages the sharing of connection。
- 避免在线程之间共享语句(及其结果集)。每次线程执行一个Statement时,它应该在放弃Connection之前先处理结果。
- 每次线程访问Connection时,它都应根据应用程序协议一致地提交或不提交。
- 只有一个线程是“管理”数据库连接线程,该线程应该处理更高级别的任务,例如建立
连接,提交,回滚,更改连接属性
例如自动提交,关闭连接,关闭
数据库(在嵌入式环境中),等等。- 关闭为了释放资源不再需要的ResultSet和语句。
答案 1 :(得分:0)
您的瓶颈不在处理1600行中-这简直是令人担忧的记录太少了,那是很小的记录。您的问题很可能类似于为请求预热新连接所需的时间(在这种情况下,并行使用2个冷连接将不会节省您的任何时间)。
查看诸如C3P0,DBCP或HikariCP之类的连接池服务,只需执行一次提取。