1.连接池创建
package lcc.dxc.DatabaseConnectionPool; import java.sql.Connection; import java.util.LinkedList; /** * @Author: * @Description: 简易的数据库连接池创建 * @Date: */ public class ConnectionPool { private LinkedList<Connection> pool = new LinkedList<>(); public ConnectionPool(int initialSize){ if(initialSize > 0){ for (int i = 0; i < initialSize ; i++) { pool.addLast(ConnectionDriver.createConnection()); } } } public void releaseConnection(Connection connection){ if(connection != null){ synchronized (pool){ //连接释放后需要进行通知,这样其他消费者能够感知到连接池中已归还了一个连接 pool.addLast(connection); pool.notifyAll(); } } } //在 mills内无法获取到连接,将返回 null public Connection fetchConnection(long mills) throws InterruptedException { synchronized (pool){ //完全超时 if(mills <= 0){ while (pool.isEmpty()){ pool.wait(); } return pool.removeFirst(); }else{ long future = System.currentTimeMillis() + mills; long remaining = mills; while (pool.isEmpty() && remaining > 0){ pool.wait(remaining); remaining = future - System.currentTimeMillis(); } Connection result = null; if(!pool.isEmpty()){ result = pool.removeFirst(); } return result; } } } }
2.由于java.sql.Connection 是一个接口,最终的实现是由数据库驱动提供方来实现的,博主只是为了娱乐,就用动态代理构造了一个Connection,改Connection的代理实现仅仅是在commit()方法调用时休眠100毫秒,如下
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.util.concurrent.TimeUnit; /** * @Author: Lcc * @Description: 数据库连接创建 * @Date: 2019/11/1 */ public class ConnectionDriver { static class ConnectionHandler implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("commit")){ TimeUnit.MILLISECONDS.sleep(100); } return null; } } //创建一个 Connection 代理,在 commit 时休眠 100 毫秒 public static final Connection createConnection(){ return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(), new Class<?>[]{Connection.class}, new ConnectionHandler()); } }
3.模拟客户端ConnectionRunner获取、使用、最后释放连接的过程,当他使用时连接将会增加获取到连接的数量,反之,将会增加未获取到连接的数量,如下:
package lcc.dxc.DatabaseConnectionPool; import java.sql.Connection; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; /** * @Author: Lcc * @Description: 数据库线程池的测试 * * @Date: 2019/11/1 */ public class ConnectionPoolTest { static ConnectionPool pool = new ConnectionPool(10); //保证所有的ConnectionRunner 能够同时开始 static CountDownLatch start = new CountDownLatch(1); //main 线程将会等待所有 ConnectionRunner 结束才能继续执行 static CountDownLatch end; public static void main(String[] args) throws InterruptedException { //线程数量,可以修改线程数量进行观察 int threadCount = 100; end = new CountDownLatch(threadCount); int count = 20; AtomicInteger got = new AtomicInteger(); AtomicInteger notGot = new AtomicInteger(); for (int i = 0; i < threadCount; i++) { Thread thread = new Thread(new ConnetionRunner(count, got, notGot), "ConnetionRunnerThread"); thread.start(); } start.countDown(); end.await(); System.out.println("total invoke:" +(threadCount * count)); System.out.println(" got connection : " + got); System.out.println(" not got connection : " + notGot); } static class ConnetionRunner implements Runnable{ int count; AtomicInteger got; AtomicInteger notGot; public ConnetionRunner(int count, AtomicInteger got, AtomicInteger notGot) { this.count = count; this.got = got; this.notGot = notGot; } @Override public void run() { try { start.await(); } catch (InterruptedException e) { } while(count > 0){ try { //从线程池中获取连接,如果1000ms内无法获取到,将会返回null //分别统计连接获取的数量got和未获取到的数量 notGot Connection connection = pool.fetchConnection(1000); if(connection != null){ try{ connection.createStatement(); connection.commit(); }finally { pool.releaseConnection(connection); got.incrementAndGet(); } }else { notGot.incrementAndGet(); } } catch (Exception e) { e.printStackTrace(); }finally { count--; } } end.countDown(); } } }
执行结果:
纯属娱乐,不喜勿喷