获取连接
package com.example.demo.conf;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//"classpath:config/config.properties"
@PropertySource({"classpath:jdbc.properties"})
@Component
public class MyJdbcConnect {
//@Value("${spring.datasource.driver-class-name}")
private static String drivter ;
// @Value("${spring.datasource.url}")
private static String url ;
// @Value("${spring.datasource.username}")
private static String username ;
// @Value("${spring.datasource.password}")
private static String password;
private Connection connection;
static {
try {
Class.forName(drivter);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public MyJdbcConnect() {
try {
connection = DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Connection getConnection(){
return connection;
}
public void close(){
try {
if (connection != null && !connection.isClosed()){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
连接池
package com.example.demo.conf;
import com.example.demo.database.MyDataSource;
import org.springframework.context.annotation.Configuration;
import java.io.InputStream;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Properties;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@Configuration
public class MyPool {
//源代码中的所有参数属性都是对外的配置
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 int maxActive=20;
private long maxWait=10000L;
private int maxIdle=10;
// 数据库连接池里的Jdbc连接有2种状态,一是正在使用中,二是用过以后又被返还的空闲中
LinkedBlockingQueue<MyJdbcConnect> busy;
LinkedBlockingQueue<MyJdbcConnect> idle;
// 目前在池子中已创建的连接数(不能大于最大连接数maxActive)
AtomicInteger createdCount = new AtomicInteger(0);
/**
* 连接池初始化
*
* @param maxActive 最大连接数量,连接数连不能超过该值
* @param maxWait 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒,当连接超过该时间便认为其实空闲连接
* @param maxIdle 最大空闲连接,当空闲连接超过该值时就挨个关闭多余的连接,但不能小于minldle
*/
public void init(int maxActive, long maxWait, int maxIdle) {
this.maxActive = maxActive;
this.maxWait = maxWait;
this.maxIdle = maxIdle;
this.busy = new LinkedBlockingQueue<>();
this.idle = new LinkedBlockingQueue<>();
}
public MyPool() {
init(maxActive,maxWait,maxIdle);
}
/**
* 从连接池中获取数据库连接。忽略poll、offer的结果判断。
*/
public MyJdbcConnect getResource() throws Exception {
MyJdbcConnect myJdbcConnect = null;
myJdbcConnect = idle.poll();
// 有空闲的可以用
if (myJdbcConnect != null) {
boolean offerResult = busy.offer(myJdbcConnect);
return myJdbcConnect;
}
// 没有空闲的,看当前已建立的连接数是否已达最大连接数maxActive
if (createdCount.get() < maxActive) {
// 已建立9个,maxActive=10。3个线程同时进来..
if (createdCount.incrementAndGet() <= maxActive) {
myJdbcConnect = new MyJdbcConnect();
boolean offerResult = busy.offer(myJdbcConnect);
return myJdbcConnect;
} else {
createdCount.decrementAndGet();
}
}
// 达到了最大连接数,需等待释放连接
myJdbcConnect = idle.poll(maxWait, TimeUnit.MILLISECONDS);
if (myJdbcConnect != null) {
boolean offerResult = busy.offer(myJdbcConnect);
return myJdbcConnect;
} else {
throw new Exception("等待超时!");
}
}
/**
* 将数据库连接返还给连接池。忽略poll、offer的结果判断。
*/
public void returnResource(MyJdbcConnect jdbcConnect) {
if (jdbcConnect == null) {
return;
}
// 忽略连接状态的检查
// jdbcConnect.getConnection().isClosed()
boolean removeResult = busy.remove(jdbcConnect);
if (removeResult) {
// 控制空闲连接的数量
if (maxIdle <= idle.size()) {
jdbcConnect.close();
createdCount.decrementAndGet();
return;
}
boolean offerResult = idle.offer(jdbcConnect);
if (!offerResult) {
jdbcConnect.close();
createdCount.decrementAndGet();
}
} else {
// 无法复用
jdbcConnect.close();
createdCount.decrementAndGet();
}
}
}
测试
package com.example.demo.conf;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.CountDownLatch;
public class Test {
final static int threadNums = 100;
private final static CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(threadNums);
public static void main(String[] args) {
// MyJdbcConnect myJdbcConnect = new MyJdbcConnect();
// Connection connection = myJdbcConnect.getConnection();
MyPool myPool = new MyPool();
for (int i = 0; i < threadNums; i++) {
new Thread(new Runnable() {
@Override
public void run() {
MyJdbcConnect resource=null;
try {
COUNT_DOWN_LATCH.await();
String sql = "select * from user";
resource = myPool.getResource();
Connection connection = resource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
resultSet.next();
System.out.println(
Thread.currentThread().getName()+"查询结果"+resultSet.getString("userEname")
);
} catch (Exception e) {
e.printStackTrace();
}finally {
myPool.returnResource(resource);
}
}
}).start();
COUNT_DOWN_LATCH.countDown();
}
}
}
配置文件获取参数
import java.io.InputStream;
import java.util.Properties;
public class ProperUtil {
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;
public void getFile(){
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"));
}
}
}