不經過鏈接池鏈接數據庫時,主要有兩大劣勢:java
1.每次操做數據庫均需鏈接數據庫,耗時;mysql
2.每次鏈接數據庫均須要單獨的線程,消耗內存嚴重,容易致使服務器宕機。sql
直接上代碼:數據庫
鏈接池接口,提供鏈接和建立鏈接:服務器
/** * @projectName:JavaProxy * @fileName:IPool.java * @packageName:club.younge.jdbc * @date:2016年10月5日下午1:21:38 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.jdbc; /** * @className:IPool * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年10月5日 下午1:21:38 * @author Younge * @version * @since JDK 1.8 * @see */ public interface IPool { public PooledConnection getConnection(); public void createConnections(int count); }
鏈接池實現類。ide
/** * @projectName:JavaProxy * @fileName:JdbcPool.java * @packageName:club.younge.jdbc * @date:2016年10月5日下午1:23:58 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.jdbc; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import java.util.Vector; import com.mysql.jdbc.Driver; /** * @className:JdbcPool * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年10月5日 下午1:23:58 * @author Younge * @version * @since JDK 1.8 * @see */ public class JdbcPool implements IPool { private String jdbcDriver; private String jdbcUser; private String jdbcPass; private String jdbcUrl; private int initConnCount; private int maxConnCount; private int incrementCount; private Vector<PooledConnection> vector = new Vector<>(); public void init(){ InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("club/younge/jdbc/jdbc.properties"); Properties properties = new Properties(); try { properties.load(in); this.jdbcDriver = properties.getProperty("jdbcDriver"); this.jdbcUrl = properties.getProperty("jdbcUrl"); this.jdbcPass = properties.getProperty("jdbcPass"); this.jdbcUser = properties.getProperty("jdbcUser"); this.initConnCount = Integer.parseInt(properties.getProperty("initalConnCount")); this.maxConnCount = Integer.parseInt(properties.getProperty("maxConnCount")); this.incrementCount = Integer.parseInt(properties.getProperty("incrementCount")); Driver driver = (Driver) Class.forName(jdbcDriver).newInstance(); DriverManager.registerDriver(driver); //註冊以後,每次建立鏈接時不用再加載驅動 createConnections(initConnCount); //建立初始鏈接 } catch (IOException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } @Override public synchronized PooledConnection getConnection() { if (vector.size() <= 0) { System.out.println("The pool has no connection to provided!"); throw new RuntimeException("The pool has no connection to provided!"); } PooledConnection conn = getActiveConnection(); if (conn == null) { createConnections(incrementCount); conn = getActiveConnection(); while(conn == null){ try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } conn = getActiveConnection(); } } return conn; } private PooledConnection getActiveConnection(){ for (PooledConnection connection : vector) { if (!connection.isBusy()) { Connection conn = connection.getConn(); try { if (!conn.isValid(0)) { conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPass); connection.setConn(conn); } } catch (SQLException e) { e.printStackTrace(); } connection.setBusy(true); return connection; } } return null; } @Override public void createConnections(int count) { for (int i = 0; i < count; i++) { if (maxConnCount > 0 && vector.size() >= maxConnCount) { System.out.println("The pool connection number has reached max count!"); throw new RuntimeException("The pool connection number has reached max count!"); } try { Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPass); vector.add(new PooledConnection(false, conn)); } catch (SQLException e) { e.printStackTrace(); } } } }
自定義鏈接類,封裝數據庫的鏈接類。測試
/** * @projectName:JavaProxy * @fileName:PooledConnection.java * @packageName:club.younge.jdbc * @date:2016年10月5日下午1:24:23 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.Statement; /** * @className:PooledConnection * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年10月5日 下午1:24:23 * @author Younge * @version * @since JDK 1.8 * @see */ public class PooledConnection { private boolean isBusy; private Connection conn; public PooledConnection() { } public PooledConnection(boolean isBusy, Connection conn){ this.isBusy = isBusy; this.conn = conn; } public ResultSet querySql(String sql){ ResultSet rs = null; try { Statement statement = (Statement) this.conn.createStatement(); rs = statement.executeQuery(sql); } catch (SQLException e) { e.printStackTrace(); } return rs; } public boolean isBusy() { return isBusy; } public void setBusy(boolean isBusy) { this.isBusy = isBusy; } public Connection getConn() { return conn; } public void setConn(Connection conn) { this.conn = conn; } public void close(){ this.isBusy = false; } }
鏈接池單例模式實現,採用內部類懶加載方式,類加載時線程互斥。this
/** * @projectName:JavaProxy * @fileName:DBManager.java * @packageName:club.younge.jdbc * @date:2016年10月5日下午2:27:10 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.jdbc; /** * @className:DBManager * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年10月5日 下午2:27:10 * @author Younge * @version * @since JDK 1.8 * @see */ public class DBManager { private static final class CreatePool{//類的加載過程是線程互斥的,同時實現懶加載,雙檢查鎖存在問題(建立對象與賦值分開進行) //具體參看博客http://blog.csdn.net/yongaini10/article/details/52738866 public static JdbcPool pool = new JdbcPool(); } public static JdbcPool getJdbcPool(){ return CreatePool.pool; } }
測試類:.net
/** * @projectName:JavaProxy * @fileName:PoolTest.java * @packageName:club.younge.test * @date:2016年10月5日下午3:22:41 * @copyright (c) 2016, heqy@finansir.nt All Rights Reserved. * */ package club.younge.test; import java.sql.ResultSet; import java.sql.SQLException; import club.younge.jdbc.DBManager; import club.younge.jdbc.JdbcPool; import club.younge.jdbc.PooledConnection; /** * @className:PoolTest * @function: TODO ADD FUNCTION. * @reason: TODO ADD REASON. * @date: 2016年10月5日 下午3:22:41 * @author Younge * @version * @since JDK 1.8 * @see */ public class PoolTest { private static JdbcPool pool; public static void main(String[] args) throws SQLException { pool = DBManager.getJdbcPool(); pool.init(); for (int i = 0; i < 100; i++) { new Thread(new Runnable() { @Override public void run() { query(); } }).start(); } } public synchronized static void query(){ System.err.println("\nCurrent thread is " + Thread.currentThread().getName()); String sql = "select * from student;"; PooledConnection connection = pool.getConnection(); ResultSet rs = connection.querySql(sql); try { while(rs.next()){ System.out.print(rs.getString("SID") + " "); System.out.print(rs.getString("SNAME") + " "); System.out.print(rs.getString("SAGE") + " "); System.out.print(rs.getString("SSEX") + " \n"); } rs.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
屬性文件,jdbc.properties:線程
jdbcDriver=com.mysql.jdbc.Driver #請自行更改數據庫鏈接信息 jdbcUrl=jdbc:mysql://127.0.0.1/test jdbcUser=root jdbcPass=xxxxx #initial connection count of jdbc pool initalConnCount=10 #maximum connection count of jdbc pool maxConnCount=100 #increment count of jdbc pool incrementCount=2