数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正式针对这个问题提出来的.数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
本人水平有限记性很差连接池原理看了忘,忘了看在这里我整理一下连接池的相关知识。想要具体的了解连接池的话请点击大神的博客
javaweb学习总结(三十九)——数据库连接池 JDBC数据库连接池
连接池基本原理:
先建立几个连接备用当需要连接时从连接池中取用完后不关闭连接还回到连接池中去
先建立如下包结构
public class JdbcPool implements DataSource {
private static LinkedList<Connection> pool=new LinkedList<>();
static {
/*
*
* this.getClass().getClassLoader().getResource("db.properties");
首先,调用对象的getClass()方法是获得对象当前的类类型,这部分数据存在方法区中,而后在类类型上调用getClassLoader()方法是得到当前类型的类加载器,我们知道在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),所以在这里通过当前类的加载器来加载资源也就是保证是和类类型同一个加载器加载的。
最后调用了类加载器的getResourceAsStream()方法来加载资源。
* ClassLoader.getResourceAsStream() 无论要查找的资源前面是否带'/' 都会从classpath的根路径下查找。
*/
InputStream in =JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");
Properties p = new Properties();
try {
p.load(in);
String driver=p.getProperty("driver");
String url=p.getProperty("url");
String username=p.getProperty(" username");
String password=p.getProperty("password");
Integer jdbcPoolInitSize=Integer.valueOf(p.getProperty("jdbcPoolInitSize"));
Class.forName(driver);
//初始化连接存到LinkedList中
for(int i=0;i<jdbcPoolInitSize;i++)
{
Connection conn=DriverManager.getConnection(url,username,password);
pool.add(conn);
}
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
/*
* 返回一个动态代理后的Connect
* 目的 :当调用Connect的close方法时不是关闭连接而是将连接返回给连接池
*
*
*
*/
@Override
public Connection getConnection() throws SQLException {
if(pool.size()>0)
{
//从连接池中移出一个对象
final Connection conn=pool.removeFirst();
return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(),conn.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(!method.getName().equals("close"))//如果调用的不是close 方法则执行Connection自身的方法
{
return method.invoke(conn, args);
}
else
{
pool.addLast(conn);//如果调用的是close方法则不关闭连接把连接重新放回连接池
}
return null;
}
});
}
else
{
System.out.println("数据库繁忙");
throw new RuntimeException("数据库繁忙");
}
}
}
上面使用动态代理实现了将用完后的连接还回连接池使得Connection的使用和没没加连接池一样。方便用户使用。但是数据库连接池一般是被多个线程访问的这个连接池没有考虑多个线程的情况。
可用于多线程访问的连接池
public class ConnectionPool {
int size=10;
//存放连接
ArrayList<Connection> conns = new ArrayList<>();
public ConnectionPool(int size)
{
this.size=size;
try
{
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try
{
//初始化连接
for(int i=0;i<size;i++)
{
Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mygame?characterEncoding=UTF-8","root", "1234");
conns.add(con);
}//for
}//try
catch(SQLException e)
{
e.printStackTrace();
}
}
public synchronized Connection getConnection()
{
while(conns.isEmpty())
{
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Connection conn = conns.remove(0);
return conn;
}
//返还连接
public synchronized void returnConnection(Connection con)
{
conns.add(con);
this.notifyAll();
}
}
参考资料:
Class.getResourceAsStream()与ClassLoader.getResourceAsStream()的区别