什么是连接池呢?
我们登陆上某个网站,去修改个人信息、点击下单、修改购买商品的数量......当我们做这些操作时候,
我们已经连接上数据库并修改、增加、删除数据库中的数据,完成操作后,关闭连接(避免占用资源)。
如果很多人访问这个网站并进行操作,那要创建很多个连接,而且只操作一次就关闭,这会显著的影响系统的
性能。连接池 就为解决这个难题应运而生。
连接池:
在系统初始化的时候,将数据库连接作为对象存放在内存中。当用户要访问数据库时,取出一个连接,
完成操作后归还到池中,等待下个用户使用。连接的创建、断开都由池来管理。我们可以设置连接池的参
数控制初始连接数、连接的上下限数、最大空闲时间......这项技术明显的提高对数据库操作的性能。
线程池:
package org3.pool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Created by Administrator on 2016/11/25.
* 编写一个线程池
*/
public class Pool {
private int minSize = 1; //定义最小连接数,默认为2
private int maxSize = 2; //定义最大连接数,默认为4
private int fetchCount = minSize; //记录从数据库抓取的连接数
private LinkedBlockingQueue<Connection> pool; //定义一个阻塞队列,充当连接池
public void setMinSize(int minSize) {
this.minSize = minSize;
this.fetchCount = minSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
//初始化线程池方法
public void initPool() {
//初始化连接池的最大值
pool = new LinkedBlockingQueue<>( maxSize );
//预先存放minSize个连接
for ( int i = 0 ; i < minSize ; i++ ) {
pool.add( DBUtil.getConnection() );
}
}
//从数据库抓取连接方法
public synchronized Connection getConnection() {
//检查连接池状况,如果检查未通过将直接引发异常,程序终止
checkFetch();
Connection conn = null;
try {
conn = getProxyConnection();
} catch (InterruptedException e) {
e.printStackTrace();
}
return conn;
}
//检查连接池的状况
private void checkFetch() {
//当连接池大小为0 且 连接记录数还没达到最大值时
if ( pool.isEmpty() && fetchCount < maxSize ) {
pool.add( DBUtil.getConnection() );
}
}
//从连接池获取连接,并将获取的连接创建一个代理对象
private Connection getProxyConnection() throws InterruptedException {
//先从池中获取未代理的连接对象
Connection conn = pool.take();
//将获取的链接创建代理对象
return createProxy( conn );
}
//使用内部类来实现InvocationHandler
private Connection createProxy( Connection conn ) {
return ( Connection )Proxy.newProxyInstance( Connection.class.getClass().getClassLoader(), new Class[] { Connection.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果客户端调用的是close方法,就将连接放回连接池
if( "close".equals(method.getName() ) ) {
pool.put( conn );
fetchCount--;
}
//如果是Connection其他的方法,将正常回调,也就是放行
return method.invoke(conn,args);
}
});
}
//查看连接池当前连接数
public int size() {
return pool.size();
}
}
DBUtil:
package org3.pool;
import java.sql.*;
/**
* Created by Administrator on 2016/11/25.
*/
public class DBUtil {
private static String driver = "oracle.jdbc.driver.OracleDriver"; //数据库驱动
private static String url = "jdbc:oracle:thin:@localhost:1521:orcl"; //数据库的资源地址
private static String userName = "mark"; //用户名
private static String password = "mark"; //密码
static {
try {
Class.forName( driver );
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection( url, userName, password );
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//main方法(用于测试)
public static void main(String[] args) {
System.out.println( getConnection() );
}
}
编写一个线程:
package org3.pool;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Created by Administrator on 2016/11/26.
* 编写线程1
*/
public class User1 extends Thread {
//定义连接池对象
private Pool pool;
public User1( Pool pool ) {
this.pool = pool;
}
//重写Thread的run方法
@Override
public void run() {
Connection conn = pool.getConnection();
System.out.println(Thread.currentThread().getName() + "获取了一个连接:" + conn);
try {
Thread.sleep( 500 );
conn.close();
System.out.println(Thread.currentThread().getName() + "归还了一个连接: " + conn);
} catch (Exception e) {
e.printStackTrace();
}
}
}
main方法:
package org3.pool;
import java.sql.SQLException;
/**
* Created by Administrator on 2016/11/25.
* main方法
*/
public class Main {
public static void main(String[] args) throws SQLException {
//实例化连接池对象
Pool pool = new Pool();
//给连接池设置属性
pool.setMinSize( 2 );
pool.setMaxSize( 5 );
//初始化连接池
pool.initPool();
for( int i = 0; i < 10; i++ ){
User1 u1 = new User1( pool );
u1.start();
}
try {
Thread.sleep( 10000 );
System.out.println( "线程大小= " + pool.size() );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:

-------------------------------------------------------------------------