我正在尝试对结果集进行多线程处理。我想确保每当我在多个线程中的一个线程内调用next()
时,所有其他线程都被锁定。这一点很重要,因为如果多个线程同时调用next()
方法,将导致跳过行。以下是我做的
public class MainClass {
private static ResultSet rs;
public static void main (String [] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
runWhile();
}});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
runWhile();
}});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.exit(0);
}
private static void runWhile () {
String username = null;
while ((username = getUsername()) != null) {
// Use username to complete my logic
}
}
/**
* This method locks ResultSet rs until the String username is retrieved.
* This prevents skipping the rows
* @return
* @throws SQLException
*/
private synchronized static String getUsername() throws SQLException {
if(rs.next()) {
return rs.getString(1).trim();
}
else
return null;
}
}
这是使用synchronized
的正确方法吗。它是否锁定ResutSet
并确保其他线程不会干扰?
这是一个好方法吗?
(由驱动程序进行锁定可能是为了驱动程序的利益,因此提供商不必处理用户滥用软件导致的比赛条件错误报告。它进行锁定并不一定意味着该软件实际上应该由多个线程使用。)
当线程可以同时进行时,多线程就会起作用,请参阅Amdahl定律。如果你有一种情况,你可以阅读结果集并使用结果创建提交给ExecutitorService的任务(正如Peter Lawrey在评论中建议的那样),那么这将更有意义(只要这些任务可以独立工作,不必相互等待)。
我建议创建ResultSet,然后将所有数据复制到DTO(数据传输对象)或DAO(数据访问对象)中。在DTO或DAO上拥有数据后,关闭ResultSet、Statement和Connection。
创建DTO/DAO以按顺序存储记录、字段和解析功能的一个非常简单的结构是:
ArrayList<HashMap<String, Object>> table = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> record = new HashMap<String, Object>();
String field1 = "something";
Integer field2 = new Integer(45);
record.put("field1", field1);
record.put ("field2", field2);
table.add(record);
您可以(可能也应该)自动化并使DTO/DAO足够灵活,可以在任何表中使用相同的类,而不需要硬代码或固定名称。
请记住,您将需要创建一个包装器和用于存储/读取数据的方法,并且这些方法应该是线程安全的。
请记住,只有当您有足够的内存来存储ResultSet的所有记录时,此设计才有效。