Java operation of the database - manually implement database connection pool

Java operation of the database - manually implement database connection pool

Abstract: This paper to learn how to manually implement a database connection pool, as well as some improvements on this basis.

Part of the contents from the following blog:

https://blog.csdn.net/soonfly/article/details/72731144

A simple database connection pool

Connection pooling tools

Queue storage resources are connected using a connection pool thread-safe, to ensure the security thread.

It provides a method to get a connection and release of the connection, connection to achieve the recycling of resources.

When thread technology, the use of atomic class, to ensure that the thread count in a multithreaded environment safety.

code show as below:

  . 1  public  class DataPoolUtils {
   2      // active connections, a thread-safe queue 
  . 3      Private  static a LinkedBlockingQueue <Connection> = BUSY new new a LinkedBlockingQueue <Connection> ();
   . 4      // idle connection, a thread-safe queue 
  . 5      Private  static a LinkedBlockingQueue <Connection > IDLE = new new a LinkedBlockingQueue <connection> ();
   . 6      // created connections, using class implements thread-safe atomic operation 
  . 7      Private  static of AtomicInteger createCount = new new of AtomicInteger (0 );
   . 8      // maximum number of connections
  9     private static int maxConnection = 5;
 10     // 最大等待毫秒数
 11     private static int maxWaitTimeout = 1000;
 12     
 13     /**
 14      * 创建连接
 15      * @return
 16      * @throws Exception 
 17      */
 18     private Connection createConnection() throws Exception {
 19         Properties pros = new Properties();
 20         InputStream is = DataPoolUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
 21         pros.load(is);
 22         String driverClass = pros.getProperty("driverClass");
 23         Class.forName(driverClass);
 24         String url = pros.getProperty("url");
 25         String user = pros.getProperty("user");
 26         String password = pros.getProperty("password");
 27         return DriverManager.getConnection(url, user, password);
 28     }
 29     
 30     /**
 31      * 关闭连接
 32      * @param connection
 33      */
 34     private void closeConnection(Connection connection) {
 35         try {
 36             if (!connection.isClosed()) {
 37                 connection.close();
 38             }
 39         } catch (SQLException e) {
 40             e.printStackTrace();
 41         }
 42     }
 43     
 44     /**
 45      * 获取连接
 46      * @return
 47      * @throwsException 
 48       * / 
49      public Connection the getConnection () throws Exception {
 50          // try to obtain idle connection 
51 is          Connection Connection = idle.poll ();
 52 is          IF (Connection == null ) {
 53 is              // attempt to create a connection, using a double check CAS is smaller than the maximum number of connections existing connections 
54 is              iF (createCount.get () < maxConnection) {
 55                  iF (createCount.incrementAndGet () <= maxConnection) {
 56 is                      connection = the createConnection ();
 57 is                  } the else{
 58                      createCount.decrementAndGet ();
 59                  }
 60              }
 61 is              // try to acquire an idle connection wait, wait for time-out mechanism to achieve 
62 is              IF (Connection == null ) {
 63 is                  Connection = idle.poll (maxWaitTimeout, TimeUnit.MILLISECONDS);
 64                  IF (connection == null ) {
 65                      the throw  new new Exception ( "Get connection timeout" );
 66                  }
 67              }
 68          }
 69          busy.offer (connection);
70          return Connection;
 71 is      }
 72      
73 is      / ** 
74       * return connection
 75       * @param Connection
 76       * / 
77      public  void the releaseConnection (Connection Connection) {
 78          // process air connection 
79          IF (Connection == null ) {
 80              createCount. decrementAndGet ();
 81              return ;
 82          }
 83          // process removes failed connection 
84          Boolean removeResult = busy.remove(connection);
 85         if (!removeResult) {
 86             closeConnection(connection);
 87             createCount.decrementAndGet();
 88             return;
 89         }
 90         // 处理已经关闭的连接
 91         try {
 92             if (connection.isClosed()) {
 93                 createCount.decrementAndGet();
 94                 return;
 95             }
 96         } catch (SQLException e) {
 97             e.printStackTrace();
 98         }
 99          // process connection failure added 
100          Boolean offerResult = idle.offer (Connection);
 101          IF (! OfferResult) {
 102              closeConnection (Connection);
 103              createCount.decrementAndGet ();
 104              return ;
 105          }
 106      }
 107 }

Test the connection pool of business class

In order to achieve the recycling of threads, thread pool needs to call the release method of connection resources, rather than directly off the connection resources.

code show as below:

. 1  public  class TestPool {
 2      // create a configuration file name of the connection pool 
. 3      Private  static DataPoolUtils the pool = new new DataPoolUtils ( );
 . 4  
. 5      / ** 
. 6       * main routine
 . 7       * / 
. 8      public  static  void main (String [] args ) {
 9          // simulate multiple query the database 
10          for ( int I = 0; I <. 6; I ++ ) {
 . 11              new new the Thread ( new new the Runnable () {
 12 is                  @Override
 13 is                  public void RUN () {
 14                      SELECT ();
 15                  }
 16              }, "thread" + I) .start ();
 . 17          }
 18 is      }
 . 19  
20 is      / ** 
21 is       * query program
 22 is       * / 
23 is      public  static  void SELECT () {
 24          connection Conn = null ;
 25          the PreparedStatement pstmt = null ;
 26 is          the ResultSet RS = null ;
 27          // get connection and executes the SQL 
28          the try {
29             conn = pool.getConnection();
30             pstmt = conn.prepareStatement("select * from student where id = 906");
31             rs = pstmt.executeQuery();
32             while (rs.next()) {
33                 System.out.println(Thread.currentThread().getName() + "\t" + rs.getString(1) + "\t" + rs.getString(2) + "\t" + rs.getString("address"));
34             }
35         } catch (Exception e) {
36             e.printStackTrace();
37         } finally {
38             // 释放资源
39             try {
40                 rs.close();
41             } catch (SQLException e) {
42                 e.printStackTrace();
43             }
44             try {
45                 pstmt.close();
46             } catch (SQLException e) {
47                 e.printStackTrace();
48             }
49             /*
50             try {
51                 conn.close();
52             } catch (SQLException e) {
53                 e.printStackTrace();
54             }
55             */
56             pool.releaseConnection(conn);
57         }
58     }
59 }

Close method using dynamic linked agent modifies native

Improved Description

Simple database connection pool already, but when in use If you call the close method native, causes the connection can not be reused.

The use of dynamic proxy learned to improve before the release of resources is still the method of connecting calls to close the pool when the method of execution.

In  DataPoolUtils  add the relevant internal class dynamic proxy class tools:

 1 /**
 2  * 代理处理类
 3  */
 4 class ConnectionInvocationHandler implements InvocationHandler{
 5     private Connection connection;
 6     private DataPoolUtils dpu;
 7 
 8     public ConnectionInvocationHandler(DataPoolUtils dpu, Connection connection) {
 9         this.dpu = dpu;
10         this.connection = connection;
11     }
12 
13     @Override
14     public Object invoke(Object proxy, Method method, Object[] args)
15              throws the Throwable {
 16          // modify the native shutdown method 
. 17          IF (method.getName () the equals ( "Close." )) {
 18 is              dpu.releaseConnection (Connection);
 . 19              return  null ;
 20 is          } the else {
 21 is              return Method .invoke (Connection, args);
 22 is          }
 23 is      }
 24 }

Modify  DataPoolUtils  tools in the  public Connection the getConnection ()  Returns the value of the method, it returns the value to the dynamic proxies:

1 return (Connection) Proxy.newProxyInstance(
2         this.getClass().getClassLoader(), 
3         new Class[] { Connection.class }, 
4         new ConnectionInvocationHandler(this, connection));

Modify  TestPool  service class  public static void SELECT ()  method, the releasable connection to close the connection:

1 try {
2     conn.close();
3 } catch (SQLException e) {
4     e.printStackTrace();
5 }

Note Note

In the tools of the  getConnection ()  Returns the proxy class method, instead of tools of  the createConnection ()  returns the process, is because the object is to get the latter into the active queue , and if the agent return in the latter object, then it will lead to activity queue objects are proxy object .

So in the implementation of the proxy object  close ()  when the method, after a dynamic proxy, the proxy object is actually being executed  releaseConnection ()  method, which is to be idle proxy object into the queue from the active queue , but because the event queue They are stored in the proxy object, resulting not from the event queue proxy object through the proxy object placed on the idle queue , which led to the connection resources have not been recycled.

Guess you like

Origin www.cnblogs.com/shamao/p/11937629.html