【发布时间】:2017-07-06 17:06:03
【问题描述】:
我正在尝试调试一个多线程应用程序,该应用程序将一个文件作为输入处理并写入 SQLite 数据库。
在应用程序中,我创建了 4 个线程,每个线程写入一个单独的 .db 文件,以防止任何同步/文件访问问题。我得到一个数据库被锁定错误,尽管我正在使用资源尝试,除了在我完成后明确关闭我打开的任何资源。这是我的代码(在线程对象内部):
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 个条目)。
【问题讨论】:
-
您不需要在 try-with-resources 块中显式关闭连接。
-
@Andy 我意识到这一点,但我这样做只是为了安全起见,因为当我只对资源使用 try 时仍然会抛出错误。
-
“锁定”表示其他人正在访问同一个数据库。您确定每个线程只使用自己的 .db 吗?
-
@CL。是的,创建文件路径时引用的“num”变量是在创建每个线程时设置的变量,我确保每个线程都为此设置了不同的值。所以第一个线程只输出到database1.db,第二个输出到databes4.db,以此类推
标签: java multithreading sqlite