Java 模拟数据库连接池的实现
前面学习过等待 - 通知机制,现在我们在其基础上添加一个超时机制,模拟从连接池中获取、使用和释放连接的过程。客户端获取连接的过程被设定为等待超时模式,即如果在 1000 毫秒内无法获取到可用连接,将会返回给客户端一个 null。设定连接池的大小为 10 个,然后通过调节客户端的线程数来模拟无法获取连接的场景
由于 java.sql.Connection 只是一个接口,最终实现是由数据库驱动提供方来实现,考虑到本例只是演示,我们通过动态代理构造一个 Connection,该 Connection 的代理仅仅是在调用 commit() 方法时休眠 100 毫秒
public class ConnectionDriver {
static class ConnectionHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("commit".equals(method.getName())) {
TimeUnit.MICROSECONDS.sleep(100);
}
return null;
}
}
/**
* 创建一个 Connection 的代理,在 commit 时休眠 100 毫秒
*/
public static Connection createConnection() {
return (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),
new Class<?>[]{Connection.class}, new ConnectionHandler());
}
}
接下来是线程池的实现。本例通过一个双向队列来维护连接,调用方需要先调用 fetchConnection(long) 方法来指定在多少毫秒内超时获取连接,当连接使用完成后,需要调用 releaseConnection(Connection) 方法将连接放回线程池
public class ConnectionPool {
private final LinkedList<Connection> pool = new LinkedList<>();
public ConnectionPool(int initialSize) {
// 初始化连接的最大上限
if (initialSize > 0) {
for (int i = 0; i < initialSize; i++) {
pool.addLast(ConnectionDriver.createConnection());
}
}
}
public void releaseConnection(Connection connection) {
if (connection != null) {
synchronized (pool) {
/* 连接释放后需要进行通知
* 这样其他消费者就能知道连接池已经归还了一个连接
*/
pool.addLast(connection);
pool.notifyAll();
}
}
}
/**
* 在给定毫秒时间内获取连接
*/
public Connection fetchConnection(long mills) throws InterruptedException {
synchronized (pool) {
// 完全超时
if (mills < 0) {
while (pool.isEmpty()) {
pool.wait();
}
return pool.removeFirst();
} else {
long future = System.currentTimeMillis() + mills;
long remaining = mills;
while (pool.isEmpty() && remaining > 0) {
pool.wait(remaining);
remaining = future - System.currentTimeMillis();
}
Connection result = null;
if (!pool.isEmpty()) {
result = pool.removeFirst();
}
return result;
}
}
}
}
最后编写一个用于模拟客户端获取连接的示例,该示例将模拟多个线程同时从连接池获取连接,并记录总尝试获取数、获取成功数和获取失败数
public class ConnectionPoolTest {
static ConnectionPool pool = new ConnectionPool(10);
static CountDownLatch start = new CountDownLatch(1);
static CountDownLatch end;
public static void main(String[] args) throws InterruptedException {
// 线程数量
int threadCount = 200;
end = new CountDownLatch(threadCount);
int count = 20;
AtomicInteger got = new AtomicInteger();
AtomicInteger notGot = new AtomicInteger();
for (int i = 0; i < threadCount; i++) {
Thread thread = new Thread(new ConnectionRunner(count, got, notGot), "ConnectionRunnerThread");
thread.start();
}
start.countDown();
end.await();
System.out.println("total invoke : " + (threadCount * count));
System.out.println("got connection : " + got);
System.out.println("not got connection : " + notGot);
}
static class ConnectionRunner implements Runnable {
int count;
AtomicInteger got;
AtomicInteger notGot;
public ConnectionRunner(int count, AtomicInteger got, AtomicInteger notGot) {
this.count = count;
this.got = got;
this.notGot = notGot;
}
@Override
public void run() {
try {
start.await();
} catch (Exception e) {
e.printStackTrace();
}
while (count > 0) {
try {
// 从线程池中获取连接,如果 1000ms 内无法获取到,将返回 null
// 分别统计获取连接的数量 got 和未获取到的数量 notGot
Connection connection = pool.fetchConnection(1000);
if (connection != null) {
try {
connection.createStatement();
connection.commit();
} finally {
pool.releaseConnection(connection);
got.incrementAndGet();
}
} else {
notGot.incrementAndGet();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
count--;
}
}
end.countDown();
}
}
}
笔者设置线程数量为 200 时,得出结果如下

当设置为 500 时,得出结果如下,当然具体结果根据机器性能而异

可见,随着客户端线程数的增加,客户端出现超时无法获取连接的比率不断升高。这种等待超时模式能保证程序出问题时,线程不会一直运行,而是按时返回,并告知客户端获取连接出现问题。数据库连接池的实际也可以应用到其他资源获取的场景,针对昂贵资源的获取都应该加以限制
Java 模拟数据库连接池的实现的更多相关文章
- java配置数据库连接池的方法步骤
java配置数据库连接池的方法步骤 java配置数据库连接池的方法步骤,需要的朋友可以参考一下 先来了解下什么是数据库连接池数据库连接池技术的思想非常简单,将数据库连接作为对象存储在一个Vecto ...
- Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池
连接池原理 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接池 ...
- Java中数据库连接池原理机制的详细讲解以及项目连接数据库采用JDBC常用的几种连接方式
连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...
- java实现数据库连接池
package com.kyo.connection; import java.sql.Connection; import java.sql.DatabaseMetaData; import jav ...
- Java jdbc数据库连接池总结!(转)
1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的 ...
- 【Java】数据库连接池技术
JDBC的问题 在程序中,我们经常要建立与数据库的连接,之后再关闭这个连接.我们知道,数据库连接对象的创建是比较消耗系统性能的,这些频繁的操作势必会消耗大量的系统资源.因此我们需要采用更高效的数据库访 ...
- java通过数据库连接池链接oracle
开发工具:Eclipse J2EE 3.6 运行环境:jdk1.6 部署环境:Tomcat7 数据库连接池用的是dbcp,网上download下来的三个jar包. 把数据库连接池包和jdbc的包放到t ...
- java常用数据库连接池 (DBCP、c3p0、Druid) 配置说明
1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库 ...
- java之数据库连接池-dbcp&c3p0&dbutils
介绍 因为数据库连接对象的创建比较消耗性能,所以可以在应用程序启动时就在内存中开辟一片空间(集合)存放多个数据库连接对象,后面需要连接时直接从该空间中取而不用新创建:使用完毕后归还连接(将连接重新放回 ...
- Java中数据库连接池原理机制的详细讲解
连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...
随机推荐
- [WPF]标记扩展(Markup Extension)
XAML是基于XML的语言,其遵循并扩展了XML的语法规则.其中一项扩展就是标记扩展(Markup Extension),比如我们经常使用的绑定Binding和x:Type. 什么是标记扩展 标记扩展 ...
- 【教程】cpp转python Nanobind 实践 加速轻量版 pythonbind11
主要是尝试一下把c++这边的函数封装打包给python用,选择nanobind的原因是:1. 优化速度快,2. 生成二进制包小,不过pythonbind11是更为广泛知道的,nanobind也是pyt ...
- 【题解】HD2016.X1,HD2016.X3,HD2016.X4,HD2016.X5
[HD2016.X1] 价钱统计 题目描述 夏天到了,超市里摆满了各种各样的应季水果.现在知道:西瓜的价钱是每斤 1.2 元:桃子的价钱是每斤 3.5 元:葡萄的价钱是每斤 4.5 元:苹果的价钱是每 ...
- JAVA学习week2
这周:根据老师在群里面推荐的JAV学习路线,初步规划了一下学习方案 并找到了相关的视频,目前来说在学习SE.学习内容:环境变量的配置和简单的hello world程序书写的注意点 下周:打算进行简单的 ...
- games101-2 透视深度插值矫正与抗锯齿分析
透视深度插值矫正与抗锯齿分析 深度插值的差错原因 透视深度插值公式推导 games101中的错误 msaa与ssaa简要定义 games101中ssaa的实现 games101中msaa的实现 深度插 ...
- Vue-cli脚手架下载安装
注意:在下载安装该脚手架之前先安装配置好NodeJS以及镜像源,NodeJS详情可查询文章:NodeJS下载安装 1.cmd中输入以下指令: npm install -g @vue/cli 整个过程中 ...
- [ABC265E] Warp
Problem Statement Takahashi is at the origin of a two-dimensional plane. Takahashi will repeat telep ...
- [python] 基于Dataset库操作数据库
dataset库是Python中一个用于操作数据库的简单库,它提供了一种简洁的方式与各种关系型数据库进行交互,例如SQLite.MySQL.PostgreSQL 等.你可以使用dataset库来执行查 ...
- Python——第一章:语言介绍
随着Python的语言在世界受欢迎程度持续高涨,如今也成功夺得了第一的宝座. 在计算机领域,没有谁(诺基亚.微软.苹果.亚马逊等等)能永远稳坐第一,随着时间更迭,就会推陈出新,一定会有更好的.更先进的 ...
- 太赞了!墙裂推荐这款网页版 Nginx 配置生成器,好用到爆!
之前民工哥也给大家介绍过一款Nginx配置生成器:强大!Nginx 配置在线一键生成"神器",不太了解的人可以去看一看. 最近民工哥又发现一款好用的网页版开源工具,同样它的功能也是 ...