JDK动态代理实现数据库连接池

1、DBConnection.java

package com.db1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnection {
	private static String drivers = DBConfig.DRIVERS;
	private static String url = DBConfig.URL;
	private static String user = DBConfig.USER;
	private static String password = DBConfig.PASSWORD;
	
	public static Connection GetConnection() { // 获取数据连接
		Connection conn = null;
		try {
			Class.forName(drivers).newInstance(); 
			//
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		 
		 try {
			 System.out.println("url------"+url);
			 System.out.println("user------"+user);
			 System.out.println("password------"+password);
			conn = DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return conn;
		}
	public static void close(Connection conn)
	{
		try {
			if(conn != null && !conn.isClosed())
			{
				conn.close();
			}
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

}
/*
 * 关闭连接
 */
		

2、Utils.java

package com.my.datasource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Utils {
	private static String drivers = DBConfig.DRIVERS;
	private static String url = DBConfig.URL;
	private static String user = DBConfig.USER;
	private static String password = DBConfig.PASSWORD;
	public static Connection GetConnection() { // 获取数据连接
		Connection conn = null;
		try {
			Class.forName(drivers).newInstance(); 
			//
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		 
		 try {
			 System.out.println("url------"+url);
			 System.out.println("user------"+user);
			 System.out.println("password------"+password);
			conn = DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return conn;
		}
	public static void close(Connection conn)
	{
		try {
			if(conn != null && !conn.isClosed())
			{
				conn.close();
			}
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

}

3、DBConfig.java

package com.db1;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class DBConfig {
	private static String db_config = "F:\\EclipseSpace\\EclipseSpace\\DBTest00\\src\\com\\db1\\dbconfig.properties";
	public static String DRIVERS = null;
	public static String URL = null;
	public static String USER = null;
	public static String PASSWORD = null;
	static  //声明静态代码块
	{
		Properties props = new Properties();
		InputStream ips = null;
		try {
			//读取属性文件
			ips = new FileInputStream(db_config);
			props.load(ips);
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		DRIVERS = props.getProperty("drivers");
		URL = props.getProperty("url");
		USER = props.getProperty("user");
		PASSWORD = props.getProperty("pwd");
	}

}

4、MyDataSource.java

package com.my.datasource;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 自定义连接池
 * @author Administrator
 *
 */
public class MyDataSource {
	//定义一个池,用于存放连接
	private static List<Connection> pool = Collections.synchronizedList(new ArrayList<>());
	//使用静态代码块给池中加入连接
	static {
		for(int i = 0; i < 10; i++) {
			Connection conn = Utils.GetConnection();
			pool.add(conn);
		}
	}
	/**
	 * 获取一个连接
	 * @return
	 */
	public static Connection removeConnection() {
		Connection conn =  pool.remove(0);
		//创建代理对象
		Connection proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(),
				conn.getClass().getInterfaces(),
				new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// TODO 自动生成的方法存根
						Object rtValue = null;
						if("close".equals(method.getName())) {
							//还回池中
							pool.add(conn);
						}
						else {
							rtValue = method.invoke(conn, args);
						}
						return rtValue;
					}
			
		});
		return proxyConn;
	}
	// 获取池中的连接数
	public static int getPoolSize() {
		return pool.size();
	}
}

5、 Test.java

package com.my.datasource;

import java.sql.Connection;
import java.sql.SQLException;

public class Test {

	public static void main(String[] args) throws SQLException {
		// TODO 自动生成的方法存根
		int size = MyDataSource.getPoolSize();
		System.out.println("使用连接之前" + size);
		for(int i = 0; i < 10; i ++) {
		Connection conn = MyDataSource.removeConnection();
		System.out.println(conn);
		try {
			//不应该关闭,应放入池中。
			conn.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		}
		
		int size1 = MyDataSource.getPoolSize();
		System.out.println("使用连接之后" + size1);
	}

}

 6、结果

二、加线程的 数据库连接池

package com.my.datapool;

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{

		@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());
	}
}
package com.my.datapool;

import java.sql.Connection;
import java.util.LinkedList;

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;
			}
		}
	}

}
package com.my.datapool;

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) {
		// 线程数量,可以修改数量进行观察
		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();
		try {
			end.await();
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		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();
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			while(count > 0) {
				//从线程池获取连接,1000ms内无法获取到,返回null
				//分别统计连接获取得数量got和未获取到的数量notGot
				try {
					Connection connection = pool.fetchConnection(1000);
					if(connection != null) {
						try {
							connection.createStatement();
							connection.commit();
						} catch (SQLException e) {
							// TODO 自动生成的 catch 块
							e.printStackTrace();
						}finally {
							pool.releaseConnection(connection);
							got.incrementAndGet();
						}
					} else {
						notGot.incrementAndGet();
					}
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				} finally {
					count --;
				}
				
			}
			end.countDown();
			
		}
		
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talNot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值