工作之余看了一下Java的等待通知机制原理,然后里面有一个数据库连接池的小Demo,觉得蛮有意思。所以看完之后,自己动手写了一个简单的实例,代码虽然简单,但是对于理解连接池还是小有帮助。话不多说,直接上代码。
链接占位:后面有时间了再来总结Java的等待通知机制
连接定义
public class Connection {
public void execute() {
try {
Thread.sleep((long) (Math.random() * 10));
} catch (InterruptedException e) {
}
}
}
连接驱动定义
public class ConnectionDriver {
public static Connection createConnection() {
return new Connection();
}
}
连接池定义
public class ConnectionPool {
private final LinkedList<Connection> pool = new LinkedList<>();
public ConnectionPool(int count) {
if (count <= 0) {
count = 1;
}
for (int i = 0;i < count;i++) {
pool.addLast(ConnectionDriver.createConnection());
}
}
public Connection fetchConnection() throws InterruptedException {
return fetchConnection(-1);
}
public Connection fetchConnection(int mil) throws InterruptedException {
synchronized (pool) {
if (mil <= 0) {
while (pool.isEmpty()) {
pool.wait();
}
return pool.removeFirst();
} else {
long fuTime = System.currentTimeMillis() + mil;
long remain = mil;
while (pool.isEmpty() && remain > 0) {
pool.wait(remain);
remain = fuTime - System.currentTimeMillis();
}
Connection result = null;
if (!pool.isEmpty()) {
result = pool.removeFirst();
}
return result;
}
}
}
public void releaseConnection(Connection connection) {
if (connection == null) {
return;
}
synchronized (pool) {
pool.addLast(connection);
pool.notifyAll();
}
}
}
连接池测试
public class ConnectionPollCeshi {
public static void main(String[] args) throws InterruptedException {
int threadCount = 10;
ConnectionPool pool = new ConnectionPool(5);
CyclicBarrier start = new CyclicBarrier(1);
CountDownLatch end = new CountDownLatch(threadCount);
AtomicInteger gotSuccess = new AtomicInteger();
AtomicInteger gotFailed = new AtomicInteger();
for (int i = 0;i < threadCount;i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
start.await();
} catch (Exception e) { }
for (int i = 0;i < 10;i++) {
try {
Connection connection = pool.fetchConnection(2);
if (connection == null) {
gotFailed.incrementAndGet();
} else {
connection.execute();
pool.releaseConnection(connection);
gotSuccess.incrementAndGet();
}
} catch (InterruptedException e) {
gotFailed.incrementAndGet();
}
}
end.countDown();
}
}).start();
}
end.await();
System.out.println("获取成功: " + gotSuccess.get());
System.out.println("获取失败: " + gotFailed.get());
}
}
运行结果
获取成功: 48
获取失败: 5
实现原理
上面使用了经典的等待通知机制,分为等待角色和通知角色,如下:
等待角色伪代码
{
while(条件不变) {
obj.wait();
}
}
通知角色伪代码
{
改变条件
obj.notifyAll();
}
对于Java等待通知里面的等待队列、同步队列还有很多值得梳理的地方,后面有时间后来认真总结,今天划水就先划到这里。