First, a PooledConnection class is created to encapsulate the connection information;
package com.bai.pool; import java.sql.Connection; /** * * Copyright: Copyright (c) 2018 LanRu-Caifu * * @ClassName: PooledConnection.java * @Description: Connection information stored in connection pool * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:48:10 am, July 29, 2010 */ public class PooledConnection { //Database connection private Connection connection; //Connection state private boolean isUsed; public PooledConnection(Connection connection,boolean isUsed) { this.connection = connection; this.isUsed = isUsed; } public Connection getConnection() { return connection; } //get,set method public void setConnection(Connection connection) { this.connection = connection; } public boolean isUsed() { return isUsed; } public void setUsed(boolean isUsed) { this.isUsed = isUsed; } /** * @Function: PooledConnection.java * @Description: Discard use of connection * * @param:Description 1 Description * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 7:02:31 PM, July 29, 2010 */ public void close() { System.out.println("Return connection use right"); this.isUsed = false; } }
Create the abstract class AbstractDataSourcePool specification of the connection pool external getConnection():
package com.bai.pool; /** * * Copyright: Copyright (c) 2018 LanRu-Caifu * * @ClassName: AbstractDataSourcePool.java * @Description: Connection pool abstract class * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:49:14 am, July 29, 2010 */ public abstract class AbstractDataSourcePool { /** * * @Function: AbstractDataSourcePool.java * @Description: How to get a connection * * @param:Description 1 Description * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:49:33 am, July 29, 2010 */ public abstract PooledConnection getConnection(); }
To implement the profile loader PropertiesPlaceHolder:
/** * Copyright © 2018 eSunny Info. Tech Ltd. All rights reserved. * * Function Description: * @Package: com.bai.pool.prop * @author: Mr white * @date: 2018 11:59:47 am, July 29, 2010 */ package com.bai.pool.prop; import java.io.InputStream; import java.util.Properties; /** * Copyright: Copyright (c) 2018 LanRu-Caifu * * @ClassName: PropertiesPlaceHolder.java * @Description: Tool class to read properties * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:59:47 am, July 29, 2010 */ public class PropertiesPlaceHolder extends Properties { private static final long serialVersionUID = 1L; public PropertiesPlaceHolder(String properties) { try { InputStream in = this.getClass().getClassLoader().getResourceAsStream(properties); //load configuration this.load(in); } catch (Exception e) { e.printStackTrace(); } } }
Configuration file jdbc.properties:
jdbc.driver.class = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://127.0.0.1:3306/ssm_ee?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true jdbc.username = root jdbc.password = root initSize = 3 maxSize = 20 incrSize = 5 timeOut = 1000
Write the core connection pool class DataSourcePool to inherit AbstractDataSourcePool:
/** * Copyright © 2018 eSunny Info. Tech Ltd. All rights reserved. * * Function Description: * @Package: com.bai.pool * @author: Mr white * @date: 2018 11:50:15 am, July 29, 2015 */ package com.bai.pool; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.util.Properties; import java.util.Vector; import java.util.concurrent.TimeUnit; import com.bai.pool.prop.PropertiesPlaceHolder; /** * Copyright: Copyright (c) 2018 LanRu-Caifu * * @ClassName: DataSourcePool.java * @Description: Function description of this class * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:50:15 am, July 29, 2015 */ public class DataSourcePool extends AbstractDataSourcePool { //Database driver name private String driverClassName; //Database connection address private String url; //Database user name private String username; //Database password private String password; //Number of initial connections private int initSize = 3; //Maximum number of connections private int maxSize = 20; //When the current connection in the connection pool has not reached the maximum number of connections after use, the number of connections initialized private int incrSize = 5; //Timeout time private int timeOut = 1000; //Polling interval milliseconds private int timeSpace = 30; //Cable object Object lockObj = new Object(); //Thread safe collection of connections public Vector<PooledConnection> connectionPool = new Vector<PooledConnection>(); public DataSourcePool() { initPool(); } /** * @Function: DataSourcePool.java * @Description: Function description of this function * * @param:Description 1 Description * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:55:27 a.m., July 29, 2010 */ private void initPool() { //Initialize the object to read the file Properties prop = new PropertiesPlaceHolder("jdbc.properties"); //Read profile information driverClassName = prop.getProperty("jdbc.driver.class"); url = prop.getProperty("jdbc.url"); username = prop.getProperty("jdbc.username"); password = prop.getProperty("jdbc.password"); //Dynamically configure connection pool information String initSizeStr = prop.getProperty("initSize"); String maxSizeStr = prop.getProperty("maxSize"); String incrSizeStr = prop.getProperty("incrSize"); String timeOutStr = prop.getProperty("timeOut"); String timeSpaceStr = prop.getProperty("timeSpace"); initSize = initSizeStr == null ? initSize : Integer.parseInt(initSizeStr); maxSize = maxSizeStr == null ? maxSize : Integer.parseInt(maxSizeStr); incrSize = incrSizeStr == null ? incrSize : Integer.parseInt(incrSizeStr); timeOut = timeOutStr == null ? timeOut : Integer.parseInt(timeOutStr); timeSpace = timeSpaceStr == null ? timeSpace : Integer.parseInt(timeSpaceStr); try {//Register the corresponding driver in DriverManager Driver driver = (Driver) Class.forName(driverClassName).newInstance(); DriverManager.registerDriver(driver); } catch (Exception e) { } } /** * @see com.bai.pool.AbstractDataSourcePool#getConnection() * @Function: DataSourcePool.java * @Description: Function description of this function * * @param:Description 1 Description * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 11:50:15 am, July 29, 2015 */ @Override public PooledConnection getConnection() { PooledConnection connection = null; synchronized(lockObj) { //Connection pool is not linked if(connectionPool.size()==0) { System.out.println("Initialize connections in the connection pool using the connection pool for the first time"); createConnections(initSize); } connection = getRealConnection(); //If you do not get to the connection poll get objects in the connection pool if(connection == null) { while(connection == null) { //Continue to create connection createConnections(incrSize); connection = getRealConnection(); try { TimeUnit.MILLISECONDS.sleep(timeSpace); } catch (Exception e) { e.printStackTrace(); } } } } return connection; } /** * @Function: DataSourcePool.java * @Description: Filter out available database connections * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 5:13:26 PM, July 29, 2010 */ private PooledConnection getRealConnection() { //Traverse connection to determine whether it is available for(int i = 0; i < connectionPool.size(); i++) { PooledConnection conn = connectionPool.get(i); if(!conn.isUsed()) { //Get java.sql.connection object Connection connection = conn.getConnection(); try { if(!connection.isValid(timeOut)) { connection = DriverManager.getConnection(url, username, password); //Make up damaged connections conn.setConnection(connection); } conn.setUsed(true); System.out.println("Get to connection object"+conn); return conn; } catch (Exception e) { e.printStackTrace(); } } } return null; } /** * @Function: DataSourcePool.java * @Description: Add connection object to connection pool * * @param:Description 1 Description * @return: Return result description * @throws: Exception description * * @version: v1.0.0 * @author: Mr white * @date: 2018 5:05:26 PM, July 29, 2010 */ private void createConnections(int initCount) { //Determine the number of connections in the pool < = maximum number of connections if(connectionPool.size() + incrSize > maxSize) { initCount = maxSize - connectionPool.size(); } //Ship connection object for(int i = 0;i<initCount; i++) { try { Connection connection = DriverManager.getConnection(url, username, password); //Load connections into objects PooledConnection conn = new PooledConnection(connection, false); connectionPool.add(conn); System.out.printf("Create the first%d A connection\n",connectionPool.size()); } catch (Exception e) { e.printStackTrace(); } } } }
Add corresponding dependency and write test class:
/** * Copyright © 2018 eSunny Info. Tech Ltd. All rights reserved. * * Function Description: * @Package: com.bai.pool * @author: Mr white * @date: 2018 6:55:37 PM, July 29, 2007 */ package com.bai.pool; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * Copyright: Copyright (c) 2018 LanRu-Caifu * * @ClassName: Test.java * @Description: Function description of this class * * @version: v1.0.0 * @author: Mr white * @date: 2018 6:55:37 PM, July 29, 2007 */ public class Test { static DataSourcePool pool = new DataSourcePool(); public static void testConnection() { PooledConnection connection = pool.getConnection(); PreparedStatement prep = null; ResultSet rs = null; try { prep = connection.getConnection().prepareStatement("select * from sys_user"); rs = prep.executeQuery(); } catch (Exception e) { e.printStackTrace(); } finally { try { if(rs != null) { rs.close(); } if(prep != null) { prep.close(); } if(connection != null) { connection.close(); } } catch (Exception e2) { e2.printStackTrace(); } } } public static void main(String[] args) { for(int i=0;i<10000;i++) testConnection(); /*new Thread(new Runnable() { @Override public void run() { testConnection(); } }).start();*/ } }
Implement single and multi-threaded testing:
As a result, a single thread always starts a single thread; the more access threads in multithreading, the more connections are occupied