我的连接管理器在java中是尽可能简单的线程安全的吗?
我尝试为运行在tomcat7服务器上的小型web应用程序创建一个尽可能简单的连接管理器。我已经找到了许多如何实现这一点的例子,但几乎总是需要JNDI和JEE,否则就没有完整的例子 我希望我的连接管理器在调用getConnection()时从连接池中传递连接,并且它是线程安全的,因此在我关闭连接之前,没有其他人使用我的连接 在我的应用程序中,我从REST服务调用ConnectionManager.getConnection(),然后在整个请求中对所有数据库调用使用该连接,并在finally子句中关闭它 有人能看一下我的代码,看看它是否足以满足我的需要。。。?两个REST调用可能会获得相同的连接,或者tomcat数据源会为我处理这一问题吗 让我的类成为一个DataSourceManager,使用一个getDataSource()方法来传递数据源,并在我的REST服务中获得与DataSourceManager.getDataSource().getConnection()的连接,是否更合适?从技术上讲,这会有什么不同吗 还是我必须用另一种方式来让它正常工作我的连接管理器在java中是尽可能简单的线程安全的吗?,java,thread-safety,datasource,connection-pooling,Java,Thread Safety,Datasource,Connection Pooling,我尝试为运行在tomcat7服务器上的小型web应用程序创建一个尽可能简单的连接管理器。我已经找到了许多如何实现这一点的例子,但几乎总是需要JNDI和JEE,否则就没有完整的例子 我希望我的连接管理器在调用getConnection()时从连接池中传递连接,并且它是线程安全的,因此在我关闭连接之前,没有其他人使用我的连接 在我的应用程序中,我从REST服务调用ConnectionManager.getConnection(),然后在整个请求中对所有数据库调用使用该连接,并在finally子句中关
import java.sql.Connection;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import se.esvenska.util.Property;
public class ConnectionManager {
private static DataSource dataSource;
private static void initDataSource() throws DatabaseException {
try {
PoolProperties p = new PoolProperties();
p.setUrl("...url...");
p.setDriverClassName("org.postgresql.Driver");
p.setUsername("...user...");
p.setPassword("...password...");
p.setDefaultAutoCommit(false);
dataSource = new DataSource();
dataSource.setPoolProperties(p);
} catch (Exception e) {
e.printStackTrace();
throw new DatabaseException(e);
}
}
public static Connection getConnection() throws Exception {
if (dataSource == null) {
initDataSource();
}
return dataSource.getConnection();
}
}
这取决于线程安全的含义。我不认为它会爆炸,但你肯定会多次调用
initDataSource
public static Connection getConnection() throws Exception {
if (dataSource == null) { // Another thread can come in after this
initDataSource(); // and before this
}
return dataSource.getConnection();
}
您需要同步该方法:
public static synchronized Connection getConnection() throws Exception {
// -----------^
if (dataSource == null) { // Now this region is
initDataSource(); // protected
}
return dataSource.getConnection();
}
我建议进行两项修改:
- 使构造函数私有化
应该是线程安全的,使用双重锁定,详细信息getConnection
getConnection()
不是线程安全的,因为数据源对于多个请求来说可能是null
。通过将initDataSource
放入datasource
字段的初始值设定器,您可以轻松解决此问题(无需锁定)。我不太了解postgresql驱动程序,所以我说不出它的池有多好(特别是在验证和资源泄漏跟踪方面)。谢谢您的评论@eckes:将数据源的初始化移到构造函数中会起作用吗?在这种情况下,不使用构造函数,它是一个单状态。@zed:如果下面的答案之一回答了您的问题,那么您可以通过单击旁边的复选标记来“接受”答案。更多:
package com.test;
import java.sql.Connection;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import se.esvenska.util.Property;
public class ConnectionManager {
private ConnectionManager() {
}
private static DataSource dataSource;
private static void initDataSource() throws DatabaseException {
try {
PoolProperties p = new PoolProperties();
p.setUrl("...url...");
p.setDriverClassName("org.postgresql.Driver");
p.setUsername("...user...");
p.setPassword("...password...");
p.setDefaultAutoCommit(false);
dataSource = new DataSource();
dataSource.setPoolProperties(p);
} catch (Exception e) {
e.printStackTrace();
throw new DatabaseException(e);
}
}
public static Connection getConnection() throws Exception {
if (dataSource == null) {
synchronized(ConnectionManager. class) {
if (dataSource == null) {
initDataSource();
}
}
}
return dataSource.getConnection();
}
}