代码之家  ›  专栏  ›  技术社区  ›  jonaslagoni

多线程程序中未释放到池的连接

  •  1
  • jonaslagoni  · 技术社区  · 7 年前

    大家好

    由于某种原因,我的连接没有被释放。我一天中大部分时间都在处理这个问题,所以现在我希望你们中的一个人能帮助我。

    数据源位于Swagger jaxws服务器中。因此,每次请求时,我都会从池中检索一个连接。这是我的DataSource类,它从池中返回连接:

    import java.beans.PropertyVetoException;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.SQLException;
    import org.apache.commons.dbcp2.BasicDataSource;
    /**
     *
     * @author Lagoni
     */
    public class DataSource {
        private static DataSource datasource;
        private BasicDataSource ds;
        private DataSource() throws IOException, SQLException, PropertyVetoException {
            ds = new BasicDataSource();
            ds.setDriverClassName("org.postgresql.Driver");
            ds.setUsername("username");
            ds.setPassword("pw");
            ds.setUrl("jdbc:postgresql://host" + 5432 + "/db");
    
            ds.setMaxWaitMillis(20000); //wait 10 seconds to get new connection
            ds.setMaxTotal(5);
            ds.setMaxIdle(5);
            ds.setTestWhileIdle(true);
            ds.setTestOnReturn(true);
            ds.setTimeBetweenEvictionRunsMillis(1000);
            ds.setSoftMinEvictableIdleTimeMillis(100); 
            ds.setMinEvictableIdleTimeMillis(10); 
            ds.setMaxConnLifetimeMillis(1000*60*10);
        }
    
        public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
            if (datasource == null) {
                datasource = new DataSource();
            }
            return datasource;
        }
    
        public Connection getConnection() throws SQLException {
            return ds.getConnection();
        }
    
    }
    

    对于需要使用数据库连接的每个函数,请通过调用来检索它:

    Connection con = DataSource.getInstance().getConnection();
    

    这就是我得到的“无法获得连接,池错误超时等待空闲对象”。我确保每个线程只使用一个连接。因此,如果函数需要对数据库进行多次调用,它将重用con变量。

    我得出的结论是,我决不应该叫骗子。close(),因为它将返回到池的空连接。使用连接完成函数时,将调用以下内容:

    resultSet.close();
    statement.close();
    

    在连接被宣布空闲之前,我是否忘记了做什么?或者我只是没有正确实现连接池?我应该试着使用另一种泳池还是?

    我使用以下maven依赖项:

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>2.1.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.4.3</version>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.1.4</version>
    </dependency>
    

    编辑1

    这是一个解决方案吗?

       try(Connection con = DataSource.getInstance().getConnection()){
            UploadedFile file = new FileServerImplementation().uploadFile(fileType, fileName, folderId, projectId, tokenString, fileInputStream, con);
            if(file != null){
                return Response.ok().entity(file).build();
            }
        }
    

    此处uploadFile方法如下:

    public UploadedFile uploadFile(String fileType, String fileName, Long folderId, Long projectId, String tokenString, InputStream fileInputStream, Connection con) throws SQLException, IOException, PropertyVetoException{
        IOController ioController = new IOController();
        DatabaseController controller = DatabaseController.getInstance();
        UploadedFile file = null;
        if(ioController.uploadFile(fileType, fileName, controller.getFolderPath(folderId, con), projectId, fileInputStream)){
            file = controller.uploadFile(fileType, fileName, folderId, projectId, con);
        }else{
            System.out.println("Error uploading " + fileName + " to folder!");
        }
        return file;
    }
    

    IOController将文件保存到磁盘上,然后方法uploadFile将一些数据上载到数据库。还是每次调用DatabaseController类中的方法时都应该从池中获取新连接?

    解决方案

    我最终使用了编辑1作为一种方法。我只需要确保在没有再次关闭它们的情况下不会创建不必要的连接。

    1 回复  |  直到 7 年前
        1
  •  2
  •   OldCurmudgeon    7 年前

    使用连接池时,您需要 close 将其释放到池以供重用的连接。做 将连接固定在螺纹中。