mysql通俗易懂的数据库连接池原理及模拟实现
什么是数据库连接池?
当系统使用 JDBC 技术访问数据库时会创建一个 connection 对象,而该对象的创建过程是非常消耗资源的,并且创建对象的时间也特别长,假设系统一天有 1 万次的访问量,那么一天就会有 1 万个 connection 对象被创建,这极大的浪费数据库的资源,而且可能造成数据库服务器内存溢出,宕机。
为了解决以上问题,就引入了数据库连接池,它主要用来分配、管理、释放数据库的连接。系统启动的时候,数据库连接池首先会创建若干个(该数量可配置)connection 对象,并将这些对象放入池中,当系统需要 connection 对象时,
数据库连接池会从池中分配一个事先创建好的 connection 对象给系统,当系统使用完毕或超时后,数据库连接池会将该 connection 对象重新放入池中。
这样就减少了创建 connection 对象所耗费的资源和时间,可以提高数据库操作的性能。
下图为数据库连接池原理图:
模拟编写一个数据库连接池
因为要用到数据库,所以需要将之前编写的 JDBC 相关的代码和 jar 包拷贝过来,创建一个 SimpleConnectionPool 类,里面需要实现下面三个功能:
1. 初始化一个数据库连接池,并向里面添加 10 个数据库连接;
2. 从连接池中获取连接;
3. 当程序用完连接后,需要将该连接重新放入连接池中。
需要注意:数据库连接池要保证线程安全!
/** * 1. 初始化一个数据库连接池,并向里面添加 10 个数据库连接; * 2. 从连接池中获取连接; * 3. 当程序用完连接后,需要将该连接重新放入连接池中。 */ public class SimpleConnectionPool {</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建一个存放连接的池子,注意要保证线程安全 </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">因为要频繁的对数据库连接池取出和存放操作,所以使用LinkedList池子</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(<span style="color: rgba(0, 0, 255, 1)">new</span> LinkedList<Connection><span style="color: rgba(0, 0, 0, 1)">()); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在类加载后向数据库连接池中存放10个数据库连接</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < 10; i++<span style="color: rgba(0, 0, 0, 1)">) { Connection con </span>=<span style="color: rgba(0, 0, 0, 1)"> DBUtil.getConnection(); pool.add(con); } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { e.printStackTrace(); } } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从连接池中获取连接</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> Connection getConnectionFromPool(){ Connection con </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断池子中是否还有连接对象</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(pool.size()>0<span style="color: rgba(0, 0, 0, 1)">){ con </span>=<span style="color: rgba(0, 0, 0, 1)"> pool.removeFirst(); }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">此时说明数据库连接池中没有可用的连接了</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("服务器忙,请稍后再试"<span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> con; } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当程序用完连接后,需要将该连接重新放入连接池中</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> release(Connection con){ pool.addLast(con); }
}
public class DBUtil {</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String driverClass="com.mysql.jdbc.Driver"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String url="jdbc:mysql://127.0.0.1:3306/map?useUnicode=true&amp;characterEncoding=utf-8"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String userName="root"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String password="root"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">{ </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">加载驱动</span>
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException{ </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> DriverManager.getConnection(url, userName, password); }
}
欢迎关注微信公众号【Java 典籍】,收看更多 Java 技术干货!
▼微信扫一扫下图↓↓↓二维码关注