首页 > 代码库 > Java数据库连接池
Java数据库连接池
写了个 Java数据库连接池,具备基本的功能点:
1、对池中活动连接的重用。
2、池满时的适时等待。
3、对空闲连接的适时关闭。
抛砖引玉,不吝赐教。
源码文件 DBConnection.java
1 package db; 2 3 import java.sql.Connection; 4 import java.util.concurrent.atomic.AtomicBoolean; 5 6 /** 7 * 封装的连接 8 * @author Linkwork, 276247076@qq.com 9 * @since 2014年11月01日10 */11 public class DBConnection {12 13 /**14 * 原生的连接15 */16 private Connection connection = null;17 18 /**19 * 是否空闲20 */21 private AtomicBoolean idle = null;22 23 /**24 * 最近一次的空闲开始时间25 */26 private volatile long idleStart = 0L;27 28 /**29 * 标识30 */31 private int index = -1;32 33 public DBConnection(int index, Connection connection, boolean idle) {34 this.index = index;35 this.connection = connection;36 this.idle = new AtomicBoolean(idle);37 }38 39 public void release() {40 if (this.idle.compareAndSet(false, true)) {41 this.idleStart = System.currentTimeMillis();42 }43 }44 45 public Connection getConnection() {46 return connection;47 }48 49 public AtomicBoolean getIdle() {50 return idle;51 }52 53 public void setConnection(Connection connection) {54 this.connection = connection;55 }56 57 public int getIndex() {58 return index;59 }60 61 public long getIdleStart() {62 return idleStart;63 }64 65 public void setIdleStart(long idleStart) {66 this.idleStart = idleStart;67 }68 69 }
源码文件 DBConnectionPool.java
1 package db; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.util.Vector; 6 7 /** 8 * 数据库连接池 9 * @author Linkwork, 276247076@qq.com 10 * @since 2014年11月01日 11 */ 12 public class DBConnectionPool extends Thread { 13 14 /** 15 * 容量 16 */ 17 private volatile int capacity = 1; 18 19 /** 20 * 驱动 21 */ 22 private String driver = null; 23 24 /** 25 * 地址 26 */ 27 private String url = null; 28 29 /** 30 * 用户名 31 */ 32 private String user = null; 33 34 /** 35 * 密码 36 */ 37 private String password = null; 38 39 /** 40 * 等待的轮询间隔 41 */ 42 private volatile long waitInterval = 50L; 43 44 /** 45 * 等待的超时时间 46 */ 47 private volatile long waitTimeout = 300000L; 48 49 /** 50 * 空闲的超时时间 51 */ 52 private volatile long idleTimeout = 60L; 53 54 /** 55 * 连接集 56 */ 57 private Vector<DBConnection> dbconnectionLst = null; 58 59 /** 60 * 是否关闭 61 */ 62 private volatile boolean closing = false; 63 64 public DBConnectionPool( 65 int capacity, 66 String driver, 67 String url, 68 String user, 69 String password) { 70 this.capacity = capacity; 71 this.driver = driver; 72 this.url = url; 73 this.user = user; 74 this.password = password; 75 this.dbconnectionLst = new Vector<DBConnection>(); 76 } 77 78 public DBConnection getDBConnection() throws Exception { 79 long start = System.currentTimeMillis(); 80 while (! this.closing) { 81 // 遍历连接集,获取空闲、可用的连接 82 for (DBConnection dbconnection: this.dbconnectionLst) { 83 if (dbconnection.getIdle().compareAndSet(true, false)) { 84 // 若连接未关闭 85 if ((null != dbconnection.getConnection()) 86 && (! dbconnection.getConnection().isClosed())) { 87 return dbconnection; 88 } else { 89 dbconnection.getIdle().set(true); 90 } 91 } 92 } 93 // 若连接的总数未超出容量 94 if ((this.dbconnectionLst.size() < this.capacity) 95 && (! this.closing)) { 96 synchronized (this.dbconnectionLst) { 97 DBConnection dbconnection = this.createDBConnection(this.dbconnectionLst.size() + 1); 98 this.dbconnectionLst.add(dbconnection); 99 return dbconnection;100 }101 } 102 // 遍历连接集,重用空闲、不可用的连接103 for (DBConnection dbconnection: this.dbconnectionLst) {104 if (dbconnection.getIdle().compareAndSet(true, false)) {105 // 若连接已关闭106 if ((null == dbconnection.getConnection())107 || dbconnection.getConnection().isClosed()) {108 Connection connection = this.createConnection();109 dbconnection.setConnection(connection);110 return dbconnection;111 } else {112 dbconnection.getIdle().set(true);113 }114 }115 }116 // 延迟轮询117 Thread.sleep(this.waitInterval);118 long end = System.currentTimeMillis();119 if (end - start > this.waitTimeout) {120 throw new Exception("ERROR_WAIT_TIMEOUT");121 }122 start = end;123 } // while (! this.closing) {124 return null;125 }126 127 public void close() throws Exception {128 this.closing = true;129 boolean closed = false;130 while (! closed) {131 closed = true;132 Thread.sleep(this.waitInterval);133 // 遍历连接集,关闭所有连接134 for (DBConnection dbconnection: this.dbconnectionLst) {135 if (dbconnection.getIdle().compareAndSet(true, false)) {136 closed = false;137 if ((null != dbconnection.getConnection())138 && (! dbconnection.getConnection().isClosed())) {139 dbconnection.getConnection().close();140 }141 }142 }143 } // while (true) {144 }145 146 @Override147 public void run() {148 while (! this.closing) {149 try {150 Thread.sleep(this.waitInterval);151 // 遍历连接集,适时关闭空闲连接152 for (DBConnection dbconnection: this.dbconnectionLst) {153 if (dbconnection.getIdle().get()154 && (dbconnection.getIdleStart() > 0)155 && (System.currentTimeMillis() - dbconnection.getIdleStart() > this.idleTimeout)) {156 if (dbconnection.getIdle().compareAndSet(true, false)) {157 if ((dbconnection.getIdleStart() > 0)158 && (System.currentTimeMillis() - dbconnection.getIdleStart() > this.idleTimeout)) {159 dbconnection.setIdleStart(0L);160 dbconnection.getConnection().close();161 System.out.println("【dbconnection-" + dbconnection.getIndex() + "】idle timeout.");162 }163 dbconnection.getIdle().set(true);164 }165 }166 }167 } catch (Exception e) {168 e.printStackTrace();169 }170 }171 }172 173 public int getCapacity() {174 return capacity;175 }176 177 public void setCapacity(int capacity) {178 this.capacity = capacity;179 }180 181 public long getWaitTimeout() {182 return waitTimeout;183 }184 185 public void setWaitTimeout(long waitTimeout) {186 this.waitTimeout = waitTimeout;187 }188 189 public long getIdleTimeout() {190 return idleTimeout;191 }192 193 public void setIdleTimeout(long idleTimeout) {194 this.idleTimeout = idleTimeout;195 }196 197 private DBConnection createDBConnection(int index) throws Exception {198 return new DBConnection(index, this.createConnection(), false);199 }200 201 private Connection createConnection() throws Exception {202 Class.forName(this.driver);203 return DriverManager.getConnection(this.url, this.user, this.password);204 }205 206 }
源码文件 DBConnectionPoolTest.java
1 package db; 2 3 import java.sql.PreparedStatement; 4 import java.sql.ResultSet; 5 6 /** 7 * 测试:数据库连接池 8 * @author Linkwork, 276247076@qq.com 9 * @since 2014年11月01日10 */11 public class DBConnectionPoolTest {12 13 public static void main(String[] args) throws Exception {14 DBConnectionPool pool = new DBConnectionPool(3, "com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/db", "Linkwork", "276247076");15 pool.start();16 DBConnection dbconnection = pool.getDBConnection();17 if (null != dbconnection) {18 dbconnection.getConnection().prepareStatement("create table if not exists test_pool (tp_value int);").execute();19 dbconnection.release();20 }21 mockConcurrent(pool);22 Thread.sleep(2000);23 mockConcurrent(pool);24 Thread.sleep(50);25 pool.close();26 }27 28 public static void mockConcurrent(DBConnectionPool pool) {29 for (int index = 0; index < 10; ++ index) {30 final int value =http://www.mamicode.com/ index;31 Thread thread = new Thread() {32 public void run() {33 DBConnection dbconnection = null;34 try {35 dbconnection = pool.getDBConnection();36 } catch (Exception e) {37 e.printStackTrace();38 }39 if (null != dbconnection) {40 try {41 if (Math.random() > 0.5) {42 PreparedStatement statement = dbconnection.getConnection().prepareStatement("insert into test_pool(tp_value) values(?);");43 statement.setInt(1, value);44 statement.execute();45 dbconnection.release();46 System.out.println("【dbconnection-" + dbconnection.getIndex() + "】insert: " + value);47 }48 else {49 PreparedStatement statement = dbconnection.getConnection().prepareStatement("select * from test_pool where tp_value = http://www.mamicode.com/?;");50 statement.setInt(1, value);51 ResultSet rs = statement.executeQuery();52 if ((null != rs)53 && rs.next()) {54 System.out.println("【dbconnection-" + dbconnection.getIndex() + "】query: " + rs.getInt(1));55 } else {56 System.out.println("【dbconnection-" + dbconnection.getIndex() + "】query: ");57 }58 dbconnection.release();59 }60 } catch (Exception e) {61 e.printStackTrace();62 }63 }64 }65 };66 thread.start();67 }68 }69 70 }
运行 DBConnectionPoolTest.java,控制台输出:
【dbconnection-1】query: 0【dbconnection-1】query: 8【dbconnection-1】query: 4【dbconnection-2】insert: 2【dbconnection-3】insert: 6【dbconnection-2】insert: 3【dbconnection-1】insert: 1【dbconnection-1】insert: 9【dbconnection-3】insert: 5【dbconnection-2】insert: 7【dbconnection-1】idle timeout.【dbconnection-2】idle timeout.【dbconnection-3】idle timeout.【dbconnection-3】query: 3【dbconnection-1】query: 1【dbconnection-2】query: 0【dbconnection-1】idle timeout.【dbconnection-2】idle timeout.【dbconnection-3】idle timeout.
说明:
这里模拟了多线程数据库请求的环境,且把数据库连接池的空闲的超时时间设置为 60毫秒(模拟适时关闭空闲连接)。
Java数据库连接池
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。