并发编程的艺术-数据库连接池简单实现

来源:互联网 发布:windows影音制作xp版 编辑:程序博客网 时间:2024/05/21 11:05

1.数据库连接池类

     

package org.global.fairy.multithread.threadpool;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.LinkedList;import java.util.concurrent.CountDownLatch;import java.util.concurrent.TimeUnit;public class ConnectionPool {private LinkedList<Connection> pool = new LinkedList<Connection>();public ConnectionPool(int size) {initialize(size);}private void initialize(int size) {try {if (size > 0) {synchronized (pool) {for (int i = 0; i < size; i++) {pool.add(ConnectionDriver.createConnection());}}}} catch (Exception e) {e.printStackTrace();}}public void releaseConnection(Connection conn) throws InterruptedException,SQLException {if (conn != null) {synchronized (pool) {pool.addLast(conn);// 释放连接后通知所有线程pool.notifyAll();}}}public Connection fetchConnection(long millons) throws InterruptedException {if (millons < 0) {// 完全超时synchronized (pool) {while (pool.isEmpty()) {pool.wait(millons);System.out.println("完全超时");}return pool.removeFirst();}} else {synchronized (pool) {long future = System.currentTimeMillis() + millons;long remaining = millons;while (pool.isEmpty() && remaining > 0) {pool.wait(remaining);remaining = future - System.currentTimeMillis();}Connection result = null;if (!pool.isEmpty()) {result = pool.removeFirst();}return result;}}}static class ConnectionDriver {static class ConnectionHandler implements InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if (method.getName().equals("commit")) {TimeUnit.MILLISECONDS.sleep(100);}return null;}}// 创建一个Connection的代理public static final Connection createConnection()throws InterruptedException, SQLException {return (Connection) Proxy.newProxyInstance(DriverManager.class.getClassLoader(),new Class<?>[] { Connection.class },new ConnectionHandler());}}}

2.模拟测试类

    

package org.global.fairy.multithread.threadpool;import java.sql.Connection;import java.sql.SQLException;import java.util.concurrent.CountDownLatch;import java.util.concurrent.atomic.AtomicInteger;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,SQLException {long startTime = System.currentTimeMillis();// 线程数量,可以修改线程数量进行观察int threadCount = 10;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();end.await();// 等待所有的线程执行完之后再打印System.out.println("total invoke:" + (threadCount * count));System.out.println("got connection:" + got);System.out.println("notGot connection:" + notGot);long cost = System.currentTimeMillis() - startTime;System.out.println("方法执行时间:" + cost);}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();} catch (Exception e) {}while (count > 0) {try {// 从线程池获取连接,如果1000ms内无法获取到,则返回null// 分别统计连接获取的数量got和未获取到的数量notGotConnection connection = pool.fetchConnection(1000);if (connection != null) {try {connection.createStatement();connection.commit();} catch (Exception e) {} finally {pool.releaseConnection(connection);got.incrementAndGet();}} else {notGot.incrementAndGet();}} catch (Exception e) {} finally {count--;}}end.countDown();}}}


个人理解:CountDownLatch类就好像埋个雷,提前准备好n个雷,然后在各个调用逻辑中调用counDown()方法把雷挨着扫出来。等所有的雷都扫出来之后,才能走到countDownwLatch的wait()方法后面的代码。

阅读全文
0 0
原创粉丝点击