Art*_*bin 8 java multithreading jdbc thread-safety
我还是一名兼职工作的大学生,因此我总是试图了解更好的做事方法.最近我不得不编写一个程序用于工作,其中程序的主线程将产生"任务"线程(对于每个数据库"任务"记录),这将执行一些操作,然后更新记录以表明它已完成.因此,我需要ThreadedTask对象中的数据库连接对象和PreparedStatement对象.
这大致是我最后写的,PreparedStatement每个线程创建一个对象是浪费吗?我认为静态PreparedStatments会造成竞争条件......
Thread A stmt.setInt(); Thread B stmt.setInt(); Thread A stmt.execute(); Thread B stmt.execute();
A版本永远不会被执行..
这个线程安全吗?创建和销毁PreparedStatement总是相同的对象并不是一个巨大的浪费?
public class ThreadedTask implements runnable {
private final PreparedStatement taskCompleteStmt;
public ThreadedTask() {
//...
taskCompleteStmt = Main.db.prepareStatement(...);
}
public run() {
//...
taskCompleteStmt.executeUpdate();
}
}
public class Main {
public static final db = DriverManager.getConnection(...);
}
Run Code Online (Sandbox Code Playgroud)
Thi*_*ilo 17
我认为在线程之间共享数据库连接(和准备好的语句)并不是一个好主意.JDBC不要求连接是线程安全的,我希望大多数驱动程序都不是.
为每个线程提供自己的连接(或者在每个查询的连接上进行同步,但这可能会破坏拥有多个线程的目的).
创建和销毁始终相同的PreparedStatement对象并不是一个巨大的浪费?
并不是的.大多数工作都发生在服务器上,如果您使用相同的SQL语句,它们将被缓存并重新使用.某些JDBC驱动程序还支持语句缓存,因此即使是客户端语句句柄也可以重用.
但是,通过使用批量查询而不是(或除了)多个线程,您可以看到实质性的改进.准备一次查询,并在一个大批量中运行它以获取大量数据.
线程安全不是问题所在.所有看起来语法和功能都很好,它应该工作大约半小时.然而,资源泄漏是真正的问题.大约半小时后应用程序将崩溃,因为您在使用后从未关闭它们.数据库将迟早关闭连接本身,以便它可以将其声明回来.
也就是说,您不必担心准备语句的缓存.JDBC驱动程序和DB将负责此任务.而是担心资源泄漏并使您的JDBC代码尽可能稳固.
public class ThreadedTask implements runnable {
public run() {
Connection connection = null;
Statement statement = null;
try {
connection = DriverManager.getConnection(url);
statement = connection.prepareStatement(sql);
// ...
} catch (SQLException e) {
// Handle?
} finally {
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
}
}
Run Code Online (Sandbox Code Playgroud)
要提高连接性能,请使用类似c3p0的连接池(顺便说一下,这并不意味着您可以更改编写JDBC代码的方式;始终在块中以尽可能短的范围获取和关闭资源).try-finally
最好使用连接池,并让每个线程向该池请求连接。在处理的连接上创建语句,记住要关闭它,并在完成后将其释放回池中。使用该池的好处是,如果发现线程并发成为问题,则可以轻松增加可用连接的数量。
| 归档时间: |
|
| 查看次数: |
12346 次 |
| 最近记录: |