用java多线程模拟数据库连接池
模拟一个ConnectionDriver,用于创建Connection
package tread.demo.threadpool; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.util.concurrent.TimeUnit; public class ConnectionDriver { static class ConnectionHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } } public static final Connection createConnection() { return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(), new Class<?>[]{Connection.class}, new ConnectionHandler()); } }
线程池的实现:
package tread.demo.threadpool; import java.sql.Connection; import java.util.LinkedList; public class ConnectionPool { private LinkedList<Connection> pool = new LinkedList<Connection>(); 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);//将Connection还回给Pool pool.notifyAll();//通知等待的线程 } } } public Connection fetchConnection(long mills) throws Exception { synchronized (pool) { if (mills <= 0) { while (pool.isEmpty()) { pool.wait();//一直等带release-》Notify } return pool.removeFirst();//得到一个connection } else { long future = System.currentTimeMillis() + mills; long remaining = mills; while (pool.isEmpty() && remaining > 0) {//基于时间进行等待,一直到超时。 pool.wait(); remaining = future - System.currentTimeMillis(); } Connection result = null; if (!pool.isEmpty()) { result = pool.removeFirst(); } return result; } } } }
两点:
- 对象的wait和notify
- 基于超时时间的等待。
测试:
package tread.demo.threadpool; import java.sql.Connection; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public class ConnectionPoolTest { static ConnectionPool pool = new ConnectionPool(10); static CountDownLatch start = new CountDownLatch(1); static CountDownLatch end; public static void main(String[] args) throws Exception { int threadCount = 1000; 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 ConnectionRunner(count, got, notGot), "ConnectionRunnerThread"); thread.start(); } start.countDown();//tart的CountDown为0,保证了所有线程同时执行。 end.await();//等待所有线程执行完毕, System.out.println("total invoke: " + (threadCount * count)); System.out.println("got connection: " + got); System.out.println("not got connection: " + notGot); } static class ConnectionRunner implements Runnable { int count; AtomicInteger got; AtomicInteger notGot; public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot) { this.count = count; this.got = got; this.notGot = notGot; } public void run() { try { start.await();//等待start的CountDown为0. } catch (InterruptedException e) { e.printStackTrace(); } while (count > 0) { try { Connection connection = pool.fetchConnection(1);//超时时间 if (connection != null) { try { connection.createStatement(); } finally { pool.releaseConnection(connection); got.incrementAndGet(); } } else { notGot.incrementAndGet(); } } catch (Exception ex) { } finally { count--; } } end.countDown(); } } }
继续巧用了CatdownLatch
结果:
total invoke: 20000 got connection: 11914 not got connection: 8086
如果调整超时时间,调整为100ms
结果如下(大部分时候都能得到connection)
total invoke: 20000 got connection: 19050 not got connection: 950
作者:iBrake
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.