繁体   English   中英

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

[英]Connections not being released to pool in multithreaded program

大家好

由于某些原因,我的连接没有被释放。 在一天的大部分时间里,我一直都在解决这个问题,所以现在我希望你们中的一个可以帮助我。

数据源位于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变量。

我得出的结论是,我永远不要调用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类中调用一个方法时都应该从池中获得一个新的连接?

我最终使用edit 1作为一种方法。 我只需要确保没有再次关闭它们就不会创建不必要的连接。

使用连接池时,需要close连接以将其释放到池中以供重新使用。 不要持有该线程的连接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM