简单模拟实现数据库连接池
实例1:
package com.bijian.thread; public class DB { //private static final int MAX_COUNT = 10; private static final DB instance = new DB(); private int count = 0; private int maxCount = 0; private DB() { } public static DB getInstance() { return instance; } public synchronized Connection getConnection() { Connection conn = new Connection(); count++; if (count > maxCount) { maxCount = count; System.out.println("(MAX)DB Connection count = " + maxCount); } return conn; } public synchronized void close() { count--; //System.out.println("(Close)DB Connection count = " + count); } }
package com.bijian.thread; public class DBUtil { private static Pool pool = new Pool(); public static Connection getConnection() throws Exception { //return DB.getInstance().getConnection(); Connection conn = null; conn = pool.getConnection(); return conn; } public static void close(Connection conn) { //DB.getInstance().close(); pool.back(conn); } }
package com.bijian.thread; public class Connection { public Connection() { try { Thread.sleep(100); } catch(Exception e) { e.printStackTrace(); } } public void execute(String sql) { try { Thread.sleep((int) Math.random() * 50); } catch(Exception e) { e.printStackTrace(); } } }
package com.bijian.thread; import java.util.ArrayList; import java.util.List; public class Pool { private static final int POOL_SIZE = 10; private List<Connection> connections = new ArrayList<Connection>(); public Pool() { for(int i = 0; i < POOL_SIZE; i++) { connections.add(DB.getInstance().getConnection()); } } public synchronized Connection getConnection() throws Exception { Connection conn = null; if (connections.size() > 0) { conn = connections.get(0); connections.remove(0); } else { wait(400); if (connections.size() > 0) { conn = connections.get(0); connections.remove(0); } else { throw new Exception("Connection Pool is empty!"); } } return conn; } public synchronized void back(Connection conn) { connections.add(conn); notify(); } }
package com.bijian.thread; public class Guest implements Runnable { private String name; public Guest(String name) { this.name = name; } @Override public void run() { Connection conn = null; try { conn = DBUtil.getConnection(); conn.execute(""); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } finally { if (conn != null) { DBUtil.close(conn); } } System.out.println(name + " executed."); } }
package com.bijian.thread; public class Main { private static final int MAX_GUEST = 100; /** * @param args */ public static void main(String[] args) { for (int i = 0; i < MAX_GUEST; i++) { new Thread(new Guest("Guest" + i)).start(); } } }
运行结果:
(MAX)DB Connection count = 1 (MAX)DB Connection count = 2 (MAX)DB Connection count = 3 (MAX)DB Connection count = 4 (MAX)DB Connection count = 5 (MAX)DB Connection count = 6 (MAX)DB Connection count = 7 (MAX)DB Connection count = 8 (MAX)DB Connection count = 9 (MAX)DB Connection count = 10 Guest75 executed. Guest74 executed. Guest73 executed. Guest79 executed. Guest81 executed. Connection Pool is empty! Guest1 executed. java.lang.Exception: Connection Pool is empty!Guest80 executed. Guest0 executed. Guest4 executed. Guest82 executed. Guest77 executed. Guest72 executed. Guest66 executed. Guest89 executed. Guest7 executed. Guest83 executed. Guest69 executed. Guest55 executed. Guest76 executed. Guest99 executed. Guest71 executed. Guest59 executed. Guest43 executed. Guest41 executed. Guest39 executed. Guest92 executed. Guest3 executed. Guest5 executed. Guest87 executed. Guest34 executed. Guest33 executed. Guest35 executed. Guest28 executed. Guest36 executed. at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) at java.lang.Thread.run(Thread.java:619) Guest98 executed. Guest42 executed. Guest15 executed. Guest16 executed. Guest46 executed. Guest38 executed. Guest40 executed. Guest44 executed. Guest94 executed. Guest45 executed. Guest51 executed. Guest49 executed. Guest63 executed. Guest93 executed. Guest57 executed. Guest85 executed. Guest50 executed. Guest60 executed. Guest56 executed. Guest58 executed. Guest86 executed. Guest68 executed. Guest70 executed. Connection Pool is empty! Connection Pool is empty! java.lang.Exception: Connection Pool is empty! at com.bijian.thread.Pool.getConnection(Pool.java:31) Guest84 executed. at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) Connection Pool is empty! at java.lang.Thread.run(Thread.java:619) Connection Pool is empty! Guest52 executed. java.lang.Exception: Connection Pool is empty! Connection Pool is empty! Connection Pool is empty! Guest65 executed. at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) Connection Pool is empty! Guest2 executed. at java.lang.Thread.run(Thread.java:619) Guest6 executed. Guest67 executed. java.lang.Exception: Connection Pool is empty! Guest90 executed. Guest88 executed. at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) at java.lang.Thread.run(Thread.java:619) Guest64 executed. Guest8 executed. Guest54 executed. Guest78 executed. java.lang.Exception: Connection Pool is empty! at com.bijian.thread.Pool.getConnection(Pool.java:31) Guest13 executed. at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) at java.lang.Thread.run(Thread.java:619) java.lang.Exception: Connection Pool is empty! Guest12 executed. Guest17 executed. Guest11 executed. Guest10 executed. Guest47 executed. Guest9 executed. Guest48 executed. at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) Guest95 executed. Guest22 executed. at com.bijian.thread.Guest.run(Guest.java:16) at java.lang.Thread.run(Thread.java:619)Guest18 executed. Guest14 executed. Guest30 executed. Guest96 executed. Guest19 executed. Guest23 executed. Guest31 executed. java.lang.Exception: Connection Pool is empty! at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) at com.bijian.thread.Guest.run(Guest.java:16) at java.lang.Thread.run(Thread.java:619) java.lang.Exception: Connection Pool is empty! Guest20 executed. Guest27 executed. at com.bijian.thread.Pool.getConnection(Pool.java:31) at com.bijian.thread.DBUtil.getConnection(DBUtil.java:10) Guest24 executed. at com.bijian.thread.Guest.run(Guest.java:16) Guest97 executed. at java.lang.Thread.run(Thread.java:619) Guest25 executed. Guest21 executed. Guest32 executed. Guest29 executed. Guest26 executed. Guest37 executed. Guest62 executed. Guest91 executed. Guest61 executed. Guest53 executed.
通过实例1简单模拟实现了数据库的连接池,但使用者获取连接时,如果连接池中没有连接时,wait 400毫秒,再次获取,如果获取不到直接报错。
修改实例1的Pool.java类(如果连接池中没有连接时,wait 400毫秒,再次获取,如果再获取不到,再wait 400毫秒……直到共wait 2分钟[当然,具体共wait多少分钟,可以具体修改]),如下实例2所示:
实例2:
package com.bijian.thread; import java.util.ArrayList; import java.util.List; public class Pool { private static final int POOL_SIZE = 10; private List<Connection> connections = new ArrayList<Connection>(); public Pool() { for(int i = 0; i < POOL_SIZE; i++) { connections.add(DB.getInstance().getConnection()); } } public synchronized Connection getConnection() throws Exception { Connection conn = null; for(int i=0;i<60*1000*2;i++) { if(connections.size() > 0) { conn = connections.get(0); connections.remove(0); break; }else { wait(400); i+=400; } } if(conn == null) { throw new Exception("Connection Pool is empty!"); } return conn; } public synchronized void back(Connection conn) { connections.add(conn); notify(); } }
运行结果(对于此模拟实例,获取连接时共wait 2 分钟,所有的连接应该都能正常获取到连接,不会抛出 Connection Pool is empty! 的异常):
(MAX)DB Connection count = 1 (MAX)DB Connection count = 2 (MAX)DB Connection count = 3 (MAX)DB Connection count = 4 (MAX)DB Connection count = 5 (MAX)DB Connection count = 6 (MAX)DB Connection count = 7 (MAX)DB Connection count = 8 (MAX)DB Connection count = 9 (MAX)DB Connection count = 10 Guest0 executed. Guest46 executed. Guest1 executed. Guest79 executed. Guest88 executed. Guest3 executed. Guest37 executed. Guest92 executed. Guest32 executed. Guest85 executed. Guest74 executed. Guest55 executed. Guest14 executed. Guest96 executed. Guest52 executed. Guest95 executed. Guest81 executed. Guest27 executed. Guest80 executed. Guest84 executed. Guest25 executed. Guest44 executed. Guest45 executed. Guest51 executed. Guest50 executed. Guest24 executed. Guest63 executed. Guest7 executed. Guest41 executed. Guest23 executed. Guest60 executed. Guest94 executed. Guest58 executed. Guest59 executed. Guest54 executed. Guest72 executed. Guest56 executed. Guest53 executed. Guest73 executed. Guest69 executed. Guest71 executed. Guest89 executed. Guest70 executed. Guest91 executed. Guest65 executed. Guest93 executed. Guest68 executed. Guest67 executed. Guest90 executed. Guest66 executed. Guest64 executed. Guest34 executed. Guest36 executed. Guest33 executed. Guest35 executed. Guest78 executed. Guest83 executed. Guest86 executed. Guest82 executed. Guest28 executed. Guest87 executed. Guest20 executed. Guest19 executed. Guest77 executed. Guest22 executed. Guest29 executed. Guest26 executed. Guest30 executed. Guest2 executed. Guest61 executed. Guest62 executed. Guest10 executed. Guest47 executed. Guest9 executed. Guest8 executed. Guest57 executed. Guest16 executed. Guest17 executed. Guest76 executed. Guest75 executed. Guest6 executed. Guest4 executed. Guest5 executed. Guest43 executed. Guest21 executed. Guest18 executed. Guest42 executed. Guest15 executed. Guest49 executed. Guest13 executed. Guest12 executed. Guest48 executed. Guest11 executed. Guest98 executed. Guest39 executed. Guest40 executed. Guest97 executed. Guest99 executed. Guest31 executed. Guest38 executed.