了解H2数据库的JdbcConnectionPool

Vol*_*ort 5 java multithreading jdbc h2

我的主服务器计算机上运行着H2服务器进程,允许进行TCP连接。

假设我要执行100个SQL查询:

SELECT * FROM TEST
Run Code Online (Sandbox Code Playgroud)

而且,出于我自己的目的,我想对每个线程进行一个查询。让我们使用Connection线程之间共享的一个和一个对象来完成此操作:

  • 创建一个Connection对象。
  • 创建100个线程。
  • 在每个线程中,使用共享库Connection调用SQL查询。

上面的方法可以工作,但是会有点慢。当然,毕竟,如果有人正在使用Connection,则其他人必须等待它。

那么,让我们Connection为每个线程做一个:

  • 创建100个线程。
  • 在每个线程中,创建一个新Connection对象并调用SQL查询。

快得多了。但是我觉得100个连接有点浪费。也许50个连接就可以了。我听说我可以用JdbcConnectionPool这种东西。

  • 建立JdbcConnectionPool最多50个连线的。
  • 创建100个线程。
  • 在每个线程中,使用pool.getConnection()然后调用SQL查询。

嗯 太慢了 如果有的话,它和第一种方法一样慢。也许出于好奇,我应该将最大连接数设置为100...

...而且仍然很慢。奇怪的。我的理解是,具有100个连接的池相当于为我的100个线程中的每个线程建立一个连接。

可能是什么问题?这是最后一个测试的代码:

import java.sql.Connection;
import java.sql.ResultSet;

import org.h2.jdbcx.JdbcConnectionPool;

public class App {

    public static void main(String[] args) throws Exception {
        Class.forName("org.h2.Driver");
        JdbcConnectionPool pool = JdbcConnectionPool.create("url", "user", "password");
        pool.setMaxConnections(100);
        for (int i = 0; i < 100; ++i) {
            Thread t = new Thread(new Client(i, pool));
            t.start();
        }
    }
}

class Client implements Runnable {
    int id;
    JdbcConnectionPool pool;
    public Client(int id, JdbcConnectionPool pool) {
        this.id = id;
        this.pool = pool;
    }
    public void run() {
        try {
            Connection conn = pool.getConnection();
            ResultSet set = conn.createStatement().executeQuery("SELECT * FROM TEST");
            if (set.next()) {
                System.out.println("Finished " + id);
            }
            set.close();
            conn.close();
        }catch (Exception e) {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用H2 1.4.182

ans*_*oyt 2

JdbcConnectionPool#getConnection()的源代码:

  public Connection getConnection() throws SQLException {
        long max = System.currentTimeMillis() + timeout * 1000;
        do {
              synchronized (this){
                if (activeConnections < maxConnections) {
                    return getConnectionNow();
                }
                try {
                    wait(1000);
                } catch (InterruptedException e) {
                    // ignore
                }
            }
        } while (System.currentTimeMillis() <= max);
        throw new SQLException("Login timeout", "08001", 8001);
    }
Run Code Online (Sandbox Code Playgroud)

您的示例中最昂贵的操作之一是创建连接。正如您所看到的,该方法getConnection()具有同步锁(this),因此只有一个线程可以同时创建连接,而所有其他线程都在等待。

我相信内置的 h2 连接池非常简单。如果你想要高性能的连接池,你可以考虑C3P0或BoneCP。