Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我的连接管理器在java中是尽可能简单的线程安全的吗?_Java_Thread Safety_Datasource_Connection Pooling - Fatal编程技术网

我的连接管理器在java中是尽可能简单的线程安全的吗?

我的连接管理器在java中是尽可能简单的线程安全的吗?,java,thread-safety,datasource,connection-pooling,Java,Thread Safety,Datasource,Connection Pooling,我尝试为运行在tomcat7服务器上的小型web应用程序创建一个尽可能简单的连接管理器。我已经找到了许多如何实现这一点的例子,但几乎总是需要JNDI和JEE,否则就没有完整的例子 我希望我的连接管理器在调用getConnection()时从连接池中传递连接,并且它是线程安全的,因此在我关闭连接之前,没有其他人使用我的连接 在我的应用程序中,我从REST服务调用ConnectionManager.getConnection(),然后在整个请求中对所有数据库调用使用该连接,并在finally子句中关

我尝试为运行在tomcat7服务器上的小型web应用程序创建一个尽可能简单的连接管理器。我已经找到了许多如何实现这一点的例子,但几乎总是需要JNDI和JEE,否则就没有完整的例子

我希望我的连接管理器在调用getConnection()时从连接池中传递连接,并且它是线程安全的,因此在我关闭连接之前,没有其他人使用我的连接

在我的应用程序中,我从REST服务调用ConnectionManager.getConnection(),然后在整个请求中对所有数据库调用使用该连接,并在finally子句中关闭它

有人能看一下我的代码,看看它是否足以满足我的需要。。。?两个REST调用可能会获得相同的连接,或者tomcat数据源会为我处理这一问题吗

让我的类成为一个DataSourceManager,使用一个getDataSource()方法来传递数据源,并在我的REST服务中获得与DataSourceManager.getDataSource().getConnection()的连接,是否更合适?从技术上讲,这会有什么不同吗

还是我必须用另一种方式来让它正常工作

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
    应该是线程安全的,使用双重锁定,详细信息


是的。我使用类似的一个已经有很多年了(不管怎么说,它看起来像是Tomcat手册的复制粘贴)您的
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();
}
}