java设计思想-池化-手写数据库连接池
池:同一类对象集合
连接池的作用
1. 资源重用
由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程 / 线程的数量)。
2. 更快的系统响应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
3. 新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,使用数据库连接池技术。设置某一应用最大可用数据库连接数,避免某一应用独占所有数据库资源。
4. 统一的连接管理,避免数据库连接泄漏
在较为完备的数据库连接池实现中,可根据预先设定的连接占用超时时间,强制收回被超时占用的连接。从而避免了常规数据库连接操作中可能出现的资源泄漏(当程序存在缺陷时,申请的连接忘记关闭,这时候,就存在连接泄漏了)。
示例
配置文件
jdbcDriver=com.mysql.jdbc.Driver
jdbcurl=jdbc:mysql://localhost:3306/mybatis
userName=root
password=root
initCount=10
stepSize=4
poolMaxSize=150
数据库连接封装
public class PooledConnection {
private boolean isBusy = false;
private Connection connection;
<span class="hljs-keyword">public</span> Connection <span class="hljs-title function_">getConnection</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> connection;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setConnection</span><span class="hljs-params">(Connection connection)</span> {
<span class="hljs-built_in">this</span>.connection = connection;
}
<span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isBusy</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> isBusy;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setBusy</span><span class="hljs-params">(<span class="hljs-type">boolean</span> isBusy)</span> {
<span class="hljs-built_in">this</span>.isBusy = isBusy;
}
<span class="hljs-keyword">public</span> <span class="hljs-title function_">PooledConnection</span><span class="hljs-params">(Connection connection, <span class="hljs-type">boolean</span> isBusy)</span> {
<span class="hljs-built_in">this</span>.connection = connection;
<span class="hljs-built_in">this</span>.isBusy = isBusy;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">close</span><span class="hljs-params">()</span> {
<span class="hljs-built_in">this</span>.isBusy = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">public</span> ResultSet <span class="hljs-title function_">queryBysql</span><span class="hljs-params">(String sql)</span> {
<span class="hljs-type">Statement</span> <span class="hljs-variable">sm</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
java.sql.<span class="hljs-type">ResultSet</span> <span class="hljs-variable">rs</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">try</span> {
sm = connection.createStatement();
rs = sm.executeQuery(sql);
} <span class="hljs-keyword">catch</span> (SQLException e) {
e.printStackTrace();
}
<span class="hljs-keyword">return</span> rs;
}
}
连接池接口
public interface IMyPool {
<span class="hljs-function">PooledConnection <span class="hljs-title">getConnection</span>()</span>;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">createConnection</span>(<span class="hljs-params"><span class="hljs-built_in">int</span> count</span>)</span>;
}
实现
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Vector;
public class MyPoolImpl implements IMyPool {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">String</span> <span class="hljs-variable">jdbcDriver</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">String</span> <span class="hljs-variable">jdbcUrl</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">String</span> <span class="hljs-variable">userName</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">String</span> <span class="hljs-variable">password</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> initCount;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> stepSize;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">int</span> poolMaxSize;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Vector<PooledConnection> pooledConnections = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Vector</span><>();
<span class="hljs-keyword">public</span> <span class="hljs-title function_">MyPoolImpl</span><span class="hljs-params">()</span> {
init();
}
<span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">init</span><span class="hljs-params">()</span> {
<span class="hljs-type">InputStream</span> <span class="hljs-variable">inputStream</span> <span class="hljs-operator">=</span> <span class="hljs-built_in">this</span>.getClass().getClassLoader().getResourceAsStream(<span class="hljs-string">"jdbc.properties"</span>);
<span class="hljs-comment">//字节信息 key value 形式化</span>
<span class="hljs-type">Properties</span> <span class="hljs-variable">pro</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Properties</span>();
<span class="hljs-keyword">try</span> {
pro.load(inputStream);
} <span class="hljs-keyword">catch</span> (IOException e) {
e.printStackTrace();
}
jdbcDriver = pro.getProperty(<span class="hljs-string">"jdbcDriver"</span>);
jdbcUrl = pro.getProperty(<span class="hljs-string">"jdbcurl"</span>);
userName = pro.getProperty(<span class="hljs-string">"userName"</span>);
password = pro.getProperty(<span class="hljs-string">"password"</span>);
initCount = Integer.valueOf(pro.getProperty(<span class="hljs-string">"initCount"</span>));
stepSize = Integer.valueOf(pro.getProperty(<span class="hljs-string">"stepSize"</span>));
poolMaxSize = Integer.valueOf(pro.getProperty(<span class="hljs-string">"poolMaxSize"</span>));
<span class="hljs-keyword">try</span> {
<span class="hljs-type">Driver</span> <span class="hljs-variable">mysqlDriver</span> <span class="hljs-operator">=</span> (Driver) Class.forName(jdbcDriver).newInstance();
DriverManager.registerDriver(mysqlDriver);
createConnection(initCount);
} <span class="hljs-keyword">catch</span> (IllegalAccessException e) {
e.printStackTrace();
} <span class="hljs-keyword">catch</span> (InstantiationException e) {
e.printStackTrace();
} <span class="hljs-keyword">catch</span> (SQLException e) {
e.printStackTrace();
} <span class="hljs-keyword">catch</span> (ClassNotFoundException e) {
e.printStackTrace();
}
}
<span class="hljs-keyword">public</span> PooledConnection <span class="hljs-title function_">getConnection</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">if</span> (pooledConnections.size() == <span class="hljs-number">0</span>) {
System.out.println(<span class="hljs-string">"获取链接管道失败,原因是连接池中没有可用管道"</span>);
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">"创建管道对象失败,原因是即将超过最大上限值"</span>);
}
<span class="hljs-comment">//连接池中的管道是没有超时 没有其他线程占用</span>
<span class="hljs-type">PooledConnection</span> <span class="hljs-variable">connection</span> <span class="hljs-operator">=</span> getRealConnection();
<span class="hljs-keyword">while</span> (connection == <span class="hljs-literal">null</span>) {
createConnection(stepSize);
connection = getRealConnection();
<span class="hljs-keyword">try</span> {
Thread.sleep(<span class="hljs-number">300</span>);
} <span class="hljs-keyword">catch</span> (InterruptedException e) {
e.printStackTrace();
}
}
<span class="hljs-keyword">return</span> connection;
}
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">createConnection</span><span class="hljs-params">(<span class="hljs-type">int</span> count)</span> {
<span class="hljs-keyword">if</span> (poolMaxSize > <span class="hljs-number">0</span> && pooledConnections.size() + count > poolMaxSize) {
System.out.println(<span class="hljs-string">"创建管道对象失败,原因是即将超过最大上限值"</span>);
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RuntimeException</span>(<span class="hljs-string">"创建管道对象失败,原因是即将超过最大上限值"</span>);
}
<span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i < count; i++) {
<span class="hljs-keyword">try</span> {
<span class="hljs-type">Connection</span> <span class="hljs-variable">conn</span> <span class="hljs-operator">=</span> DriverManager.getConnection(jdbcUrl, userName, password);
<span class="hljs-type">PooledConnection</span> <span class="hljs-variable">pooledConnection</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PooledConnection</span>(conn, <span class="hljs-literal">false</span>);
pooledConnections.add(pooledConnection);
} <span class="hljs-keyword">catch</span> (SQLException e) {
e.printStackTrace();
}
}
}
<span class="hljs-keyword">private</span> <span class="hljs-keyword">synchronized</span> PooledConnection <span class="hljs-title function_">getRealConnection</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">for</span> (PooledConnection conn : pooledConnections) {
<span class="hljs-keyword">if</span> (!conn.isBusy()) {
<span class="hljs-type">Connection</span> <span class="hljs-variable">connection</span> <span class="hljs-operator">=</span> conn.getConnection();
<span class="hljs-keyword">try</span> {
<span class="hljs-comment">//发送一个信息给数据库 2000毫秒内 收到返回信息 认为 这个管道没有超时</span>
<span class="hljs-keyword">if</span> (!connection.isValid(<span class="hljs-number">2000</span>)) {
<span class="hljs-type">Connection</span> <span class="hljs-variable">validConn</span> <span class="hljs-operator">=</span> DriverManager.getConnection(jdbcUrl, userName, password);
conn.setConnection(validConn);
}
} <span class="hljs-keyword">catch</span> (SQLException e) {
e.printStackTrace();
}
conn.setBusy(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">return</span> conn;
}
}
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
}
连接池管理
public class PoolManager {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">createPool</span> {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">MyPoolImpl</span> <span class="hljs-variable">poolImpl</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPoolImpl</span>();
}
<span class="hljs-comment">/**
* 内部类单利模式产生使用对象
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> MyPoolImpl <span class="hljs-title function_">getInstance</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> createPool.poolImpl;
}
}
测试类
import java.sql.ResultSet;
import java.sql.SQLException;
public class MypoolTest {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> MyPoolImpl poolImpl = PoolManager.getInstance();
<span class="hljs-function"><span class="hljs-keyword">public</span> synchronized <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">selctData</span>()</span> {
PooledConnection connection = poolImpl.getConnection();
ResultSet rs = connection.queryBysql(<span class="hljs-string">"SELECT * FROM user"</span>);
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">while</span> (rs.next()) {
System.<span class="hljs-keyword">out</span>.println(rs.getString(<span class="hljs-string">"ID"</span>) + <span class="hljs-string">"\t\t"</span>);
System.<span class="hljs-keyword">out</span>.println(rs.getString(<span class="hljs-string">"USERNAME"</span>) + <span class="hljs-string">"\t\t"</span>);
System.<span class="hljs-keyword">out</span>.println(rs.getString(<span class="hljs-string">"PASSWORD"</span>) + <span class="hljs-string">"\t\t"</span>);
System.<span class="hljs-keyword">out</span>.println();
}
rs.close();
connection.close();
} <span class="hljs-keyword">catch</span> (SQLException e) {
e.printStackTrace();
}
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(<span class="hljs-params">String[] args</span>)</span> {
<span class="hljs-keyword">for</span> (<span class="hljs-built_in">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">1500</span>; i++) {
<span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> Runnable() {
@Override
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span>()</span> {
selctData();
}
}).start();
}
}
}