- .连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。也是复用连接。
连接池简易设计图
代码
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/njdx?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
jdbc.maxActive=50
jdbc.initialSize=5
jdbc.stepSize = 5/**
* 连接池方法接口
*
* @Author yjian
* @Date 16:08 2017/10/14
**/
public interface IDataBasePool {
//对外提供管道
PooledConnection getConnection();
//对内创建链接
void createConnections(int count);
}
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;
/**
* 连接池实现
*
* @Author yjian
* @Date 16:40 2017/10/14
**/
public class DataBasePoolImpl implements IDataBasePool {
//源代码中的所有参数属性都是对外的配置
private static String driver = null;
private static String url = null;
private static String user = null;
private static String password = null;
//限制连接池中的管道数量参数
private static int initCount = 4;
private static int stepSize = 10;
private static int poolMaxSize = 150;
//线程安全的集合 用来放我们的连接管道
private static Vector<PooledConnection> pooledConnections = new Vector<PooledConnection>();
public DataBasePoolImpl() {
init();
}
/**
* 初始化 解析配置文件并创建连接池
*
* @Author yjian
* @Date 16:33 2017/10/14
**/
public void init() {
//获得连接池配置并读取
InputStream input = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
try {
properties.load(input);
} catch (Exception e) {
e.printStackTrace();
}
//解析数据
driver = properties.getProperty("jdbc.driverClassName");
url = properties.getProperty("jdbc.url");
user = properties.getProperty("jdbc.username");
password = properties.getProperty("jdbc.password");
//对字节信息进行判断
if (Integer.valueOf(properties.getProperty("jdbc.initialSize")) > 0) {
initCount = Integer.valueOf(properties.getProperty("jdbc.initialSize"));
}
if (Integer.valueOf(properties.getProperty("jdbc.maxActive")) > 0) {
poolMaxSize = Integer.valueOf(properties.getProperty("jdbc.maxActive"));
}
if (Integer.valueOf(properties.getProperty("jdbc.stepSize")) > 0) {
stepSize = Integer.valueOf(properties.getProperty("jdbc.stepSize"));
}
//准备创建什么类型管道
try {
//反射
Driver dbDriver = (Driver) Class.forName(driver).newInstance();
//注册
DriverManager.registerDriver(dbDriver);
} catch (Exception e) {
e.printStackTrace();
}
//开始创建连接池
createConnections(initCount);
}
/**
* 从连接池获取有效的连接,如果没有会容错创建
*
* @Author yjian
* @Date 16:31 2017/10/14
**/
public PooledConnection getRealConnection() {
for (PooledConnection conn : pooledConnections) {
if (!conn.isBuy()) {
//获得物理连接
Connection connection = conn.getConnection();
try {
//发送一个指令给数据库,看是否收到回应
if (!connection.isValid(2000)) {
connection = DriverManager.getConnection(url, user, password);
}
} catch (SQLException e) {
e.printStackTrace();
}
//设置当前连接被占用
conn.setBuy(true);
return conn;
}
}
return null;
}
@Override
public PooledConnection getConnection() {
//容错性校验
if (pooledConnections.size() == 0) {
System.out.println("获取数据库连接管道失败");
//手动刷新
createConnections(initCount);
}
PooledConnection pooled = getRealConnection();
while (pooled == null) {
createConnections(stepSize);
pooled = getRealConnection();
//防止被其他人抢了
try {
Thread.sleep(20);
} catch (Exception e) {
e.printStackTrace();
}
}
return pooled;
}
@Override
public void createConnections(int count) {
//判断是否超过连接池最大限制
if (pooledConnections.size() + count <= poolMaxSize) {
for (int i = 0; i < initCount; i++) {
try {
//创建连接
Connection connection = DriverManager.getConnection(url, user, password);
//封装
PooledConnection pooled = new PooledConnection(false, connection);
//加入连接池
pooledConnections.add(pooled);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("初始化" + (i + 1) + "个管道");
}
} else {
System.out.println("超过连接池最大限制");
}
}
}
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* 连接池实体
*/
public class PooledConnection {
//标识繁忙标识 复用的标志 线程安全
private boolean isBuy = false;
//物理连接(连接数据库的)
private Connection connection;
//数据库操作
public ResultSet queryBySql(String sql) {
Statement sm = null;
ResultSet rs = null;
try {
sm = connection.createStatement();
rs = sm.executeQuery(sql);
} catch (Exception e) {
e.printStackTrace();
}
return rs;
}
//这个功能也是自定义添加 是否链接
public void close() {
this.isBuy = false;
}
public PooledConnection(boolean isBuy, Connection connection) {
this.isBuy = isBuy;
this.connection = connection;
}
public boolean isBuy() {
return isBuy;
}
public void setBuy(boolean buy) {
isBuy = buy;
}
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
}
/**
* 内部类单列模式
*
* @Author yjian
* @Date 16:40 2017/10/14
**/
public class DataBaseSingleton {
private static class createDataBasePool {
private static DataBasePoolImpl poolImp = new DataBasePoolImpl();
}
/**
* 内部类单列模式,仿造类加载原理完美实现线程安全问题 JDK加载时内部类,线程互斥保证了线程安全
*
* @Author yjian
* @Date 16:37 2017/10/14
**/
public static DataBasePoolImpl getInstace() {
return createDataBasePool.poolImp;
}
}import java.sql.ResultSet;
/**
* 连接池测试类
*
* @Author yjian
* @Date 16:39 2017/10/14
**/
@SuppressWarnings("ALL")
public class DataBasePoolTest {
//内部类单例模式
private static DataBasePoolImpl poolImpl = DataBaseSingleton.getInstace();
public synchronized static void selectData() {
//获取连接池
PooledConnection connection = poolImpl.getConnection();
ResultSet rs = connection.queryBySql("select * from test");
System.out.println("线程名称:" + Thread.currentThread().getName());
try {
while (rs.next()) {
System.out.println(rs.getInt("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getString("nums"));
System.out.println();
}
//释放
rs.close();
//释放当前连接
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
for (int i = 0; i < 1500; i++) {
new Thread(new Runnable() {
public void run() {
selectData();
}
}).start();
}
}
}版权声明:本文为yingfengjia520原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。