我正在尝试调试多线程应用程序,该应用程序将一个文件作为输入处理并写入SQLite数据库。
在应用程序中,我创建了4个线程,每个线程都写入一个单独的.db文件,以防止出现任何同步/文件访问问题。我得到的数据库是锁定错误,尽管我正在使用try资源,除了明确关闭我完成后打开的任何资源。这是我的代码(在线程对象内部):
public void run() {
String path = database + num + ".db";
try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + path);
PreparedStatement insertReview = conn.prepareStatement("insert into reviews (" +
"reviewerID, " +
"asin, " +
"rating, " +
"title, " +
"content, " +
"helpfulVotes, " +
"totalVotes) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);");) {
System.out.println("Writing from thread " + num);
Class.forName("org.sqlite.JDBC");
int x = 1;
for (Object[] review : reviews) {
insertReview.setString(1, (String) review[0]);
insertReview.setString(2, (String) review[1]);
insertReview.setDouble(3, (Double) review[2]);
insertReview.setString(4, (String) review[3]);
insertReview.setString(5, (String) review[4]);
insertReview.setInt(6, Integer.parseInt((String) review[5]));
insertReview.setInt(7, Integer.parseInt((String) review[6]));
insertReview.addBatch();
//System.out.println("Processed review " + x + " of " + reviews.size() + " in " + num);
x++;
}
conn.setAutoCommit(false);
System.out.println("Executing batch in " + num);
insertReview.executeBatch();
insertReview.close();
conn.commit();
conn.close();
}
catch (Exception e) {
System.out.println("Thread" + num);
e.printStackTrace();
System.exit(1);
}
}
正如您所看到的,我使用“try with resource”打开连接和预准备语句,然后在try块的末尾关闭它们。会发生什么事情,该程序将运行一段时间(线程正在创建,运行和死亡),然后我似乎随机得到这个:
java.sql.SQLException: database is locked
指向我所在的行
insertReview.executeBatch();
或
conn.commit();
或我创建预准备语句的try声明中的行,并且抛出异常的线程似乎也是随机的。
我完全不知道为什么,因为我很肯定,一旦我不再需要它,我就会关闭所有资源。
编辑:我只想强调,例外情况似乎是随机抛出的。有时它会在线程第一次尝试执行批处理时抛出,有时程序会在没有问题的情况下运行一段时间(在进程中创建线程,这些都运行得非常好),直到抛出异常为止。它与目前程序处理的数据量没有关联(从0到60,000个条目)。答案 0 :(得分:0)
检查executeBatch()和commit()是否都是同步函数...此外,您可以尝试将数据库设置为序列化或多线程模式以防万一。