Hikari目前已经是springboot的默认数据库连接池,并且以高效和轻量著称,因为代码量比较少,所以可以阅读一下,学习一下,github地址:HikariCP
SuspendResumeLock
数据库连接池暂停恢复锁。如果hikari配置中设置isAllowPoolSuspension为true,那么就会在HikariPool中实例一个暂停恢复锁。
空锁
public static final SuspendResumeLock FAUX_LOCK = new SuspendResumeLock(false) {
@Override
public void acquire() {}
@Override
public void release() {}
@Override
public void suspend() {}
@Override
public void resume() {}
};
类中首先创建了一个单例空锁,中间没有实现任何方法,这个对象是用在连接池不需要暂停恢复锁时传入的对象。
成员变量
-
private static final int MAX_PERMITS = 10000;
信号量最大值为10K -
private final Semaphore acquisitionSemaphore;
这个Semaphore信号量在当时阅读《JAVA并发编程实战》中看到过,笔记描述为:
Semaphore中管理着一组虚拟的许可(permit),许可的初始数量可通过构造函数来指定,在执行操作时可以首先获取许可(只要还有剩余的许可),并在使用以后释放许可。如果没有许可,那么acquire将阻塞直到有许可(或者直到被中断或者操作超时)。release方法将返回一个许可给信号量。计算信号量的一种简化形式是二值信号量,即初始值为1的Semaphore。二值信号量可以用做互斥体(mutex),并具备不可重入的加锁语义:谁拥有这个唯一的许可,谁就拥有了互斥锁。
release返回许可信号量的实现不包含真正的许可对象,而且Semaphore也不会将许可和线程关联起来,因此在一个线程中获取的许可可以在另一个线程中释放。可以将acquire操作视为是消费一个许可,而release操作是创建一个许可,Semaphore并不受限于它在创建时的初始许可数量。
按照笔记中的描述,其实就是在限制连接的数量,如果连接超过10K,那么就会阻塞直到有别的连接断开后释放了信号量。这是控制IO流量的一种常见的方式。
构造方法
public SuspendResumeLock()
{
this(true);
}
private SuspendResumeLock(final boolean createSemaphore)
{
acquisitionSemaphore = (createSemaphore ? new Semaphore(MAX_PERMITS, true) : null);
}
默认构造器是带锁的,信号量的值为10K
Semaphore方法
- public void acquire()
public void acquire() throws SQLException
{
if (acquisitionSemaphore.tryAcquire()) {
return;
}
else if (Boolean.getBoolean("com.zaxxer.hikari.throwIfSuspended")) {
throw new SQLTransientException("The pool is currently suspended and configured to throw exceptions upon acquisition");
}
acquisitionSemaphore.acquireUninterruptibly();
}
获取信号量方法,首先会尝试获取信号量,如果没有获取到并且配置文件配置了获取不到抛出异常,那么就会抛出sql异常。如果没有配置,那么就调用acquireUninterruptibly()方法继续等待获取信号量
- public void release()
public void release()
{
acquisitionSemaphore.release();
}
释放线程持有的信号量
- public void suspend()
public void suspend()
{
acquisitionSemaphore.acquireUninterruptibly(MAX_PERMITS);
}
获取所有信号量导致暂停
- public void resume()
public void resume()
{
acquisitionSemaphore.release(MAX_PERMITS);
}
释放所有信号量恢复连接池