另一版本请查看本人博客:《黑马JUC——自定义连接池:享元模式+AtomicIntegerArray+synchronized+wait()+notify()》
一个线上商城应用,QPS 达到数千,如果每次都重新创建和关闭数据库连接,性能会受到极大影响。 这时 预先创建好一批连接,放入连接池。一次请求到达后,从连接池获取连接,使用完毕后再还回连接池,这样既节约 了连接的创建和关闭时间,也实现了连接的重用,不至于让庞大的连接数压垮数据库。
实现
连接池
/**
* 自定义线程池
*/
@Slf4j(topic = "c.eight-Demo1")
class ConnectionPool{
//1.连接池大小
private final int size;
//2.连接对象数组
private Connection[] connections;
//3.连接状态数组 0:空闲 1:忙碌
private AtomicIntegerArray status;
//信号量
Semaphore signal ;
//4.构造器初始化
ConnectionPool(int size) {
this.size=size;
connections = new Connection[size];
status=new AtomicIntegerArray(new int[size]);
signal= new Semaphore(size);
for (int i = 0; i < size; i++) {
connections[i]=new com.example.create.eight.DiyConnection();
}
}
//5.借连接
public Connection borrow() {
while (true){
//信号量加1
try {
signal.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
//成功,获取空闲连接
for (int i = 0; i < size; i++) {
if(status.get(i)==0){
if (status.compareAndSet(i,0,1)) {
log.debug("获得连接"+i);
return connections[i];
}
}
}
}
}
//6.还连接
public void fee(Connection connection){
for (int i = 0; i < size; i++) {
if(connections[i]==connection){
log.debug("释放连接"+i);
status.set(i,0);
//信号量减1
signal.release();
break;
}
}
}
}
连接对象
class DiyConnection implements Connection{
//略
}
测试
代码
public static void main(String[] args) {
com.example.create.eight.ConnectionPool pool = new com.example.create.eight.ConnectionPool(2);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
Connection conn = pool.borrow();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.fee(conn);
}).start();
}
}
输出
16:56:20 [Thread-0] c.seven-Demo1 - 获得连接1
16:56:20 [Thread-1] c.seven-Demo1 - 获得连接0
16:56:21 [Thread-0] c.seven-Demo1 - 释放连接1
16:56:21 [Thread-1] c.seven-Demo1 - 释放连接0
16:56:21 [Thread-2] c.seven-Demo1 - 获得连接0
16:56:21 [Thread-3] c.seven-Demo1 - 获得连接1
16:56:22 [Thread-3] c.seven-Demo1 - 释放连接1
16:56:22 [Thread-2] c.seven-Demo1 - 释放连接0
16:56:22 [Thread-4] c.seven-Demo1 - 获得连接1
16:56:23 [Thread-4] c.seven-Demo1 - 释放连接1