Java 鏈接池的工做原理

什麼是鏈接?java

鏈接,是咱們的編程語言與數據庫交互的一種方式。咱們常常會聽到這麼一句話「數據庫鏈接很昂貴「。mysql

有人接受這種說法,殊不知道它的真正含義。所以,下面我將解釋它到底是什麼。[若是你已經知道了,你能夠跳到它的工做原理部分]sql

建立鏈接的代碼片斷:數據庫

?編程

1數組

2dom

3編程語言

String connUrl = "jdbc:mysql://your.database.domain/yourDBname"; ide

Class.forName("com.mysql.jdbc.Driver"); url

Connection con = DriverManager.getConnection (connUrl);

 

當咱們建立了一個Connection對象,它在內部都執行了什麼:

1.「DriverManager」檢查並註冊驅動程序,
2.「com.mysql.jdbc.Driver」就是咱們註冊了的驅動程序,它會在驅動程序類中調用「connect(url…)」方法。
3.com.mysql.jdbc.Driver的connect方法根據咱們請求的「connUrl」,建立一個「Socket鏈接」,鏈接到IP爲「your.database.domain」,默認端口3306的數據庫。
4.建立的Socket鏈接將被用來查詢咱們指定的數據庫,並最終讓程序返回獲得一個結果。

爲何昂貴?

如今讓咱們談談爲何說它「昂貴「。

若是建立Socket鏈接花費的時間比實際的執行查詢的操做所花費的時間還要更長。

這就是咱們所說的「數據庫鏈接很昂貴」,由於鏈接資源數是1,它須要每次建立一個Socket鏈接來訪問DB。

所以,咱們將使用鏈接池。

鏈接池初始化時建立必定數量的鏈接,而後從鏈接池中重用鏈接,而不是每次建立一個新的。

怎樣工做?

接下來咱們來看看它是如何工做,以及如何管理或重用現有的鏈接。

咱們使用的鏈接池供應者,它的內部有一個鏈接池管理器,當它被初始化:

1.它建立鏈接池的默認大小,好比指定建立5個鏈接對象,並把它存放在「可用」狀態的任何集合或數組中。

例如,代碼片斷:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

...

  String connUrl = "jdbc:mysql://your.database.domain/yourDBname";

  String driver = "com.mysql.jdbc.Driver";

  private Map<java.sql.Connection, String> connectionPool = null;

  private void initPool() {

    try {

      connectionPool = new HashMap<java.sql.Connection, String>();

      Class.forName(driver);

      java.sql.Connection con = DriverManager.getConnection(dbUrl);

      for (int poolInd = poolSize; poolInd < 0; poolInd++) {

        connectionPool.put(con, "AVAILABLE");

      }

  }

...

 

2.當咱們調用connectionProvider.getConnection(),而後它會從集合中獲取一個鏈接,固然狀態也會更改成「不可用」。

例如,代碼片斷:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

...

  public java.sql.Connection getConnection() throws ClassNotFoundException, SQLException

  {

      boolean isConnectionAvailable = true;

      for (Entry<java.sql.Connection, String> entry : connectionPool.entrySet()) {

          synchronized (entry) {

              if (entry.getValue()=="AVAILABLE") {

                  entry.setValue("NOTAVAILABLE");

                  return (java.sql.Connection) entry.getKey();

              }

              isConnectionAvailable = false;

          }

      }

      if (!isConnectionAvailable) {

          Class.forName(driver);

          java.sql.Connection con = DriverManager.getConnection(connUrl);

          connectionPool.put(con, "NOTAVAILABLE");

          return con;

      }

      return null;

  }

  ...

3.當咱們關閉獲得的鏈接,ConnectionProvider是不會真正關閉鏈接。相反,只是將狀態更改成「AVAILABLE」。

例如,代碼片斷:

?

1

2

3

4

5

6

7

8

9

10

11

12

...

public void closeConnection(java.sql.Connection connection) throws ClassNotFoundException, SQLException {

    for (Entry<java.sql.Connection, String> entry : connectionPool.entrySet()) {

        synchronized (entry) {

            if (entry.getKey().equals(connection)) {

                //Getting Back the conncetion to Pool

                entry.setValue("AVAILABLE");

            }

        }

    }

}

...

 

基本上鍊接池的實際工做原理就是這樣,但也有可能使用不一樣的方式。

如今,你可能有一個問題,咱們是否能夠創造咱們本身的鏈接池機制?
 
個人建議是使用已經存在的鏈接池機制,像C3P0DBCP等。

相關文章
相關標籤/搜索