源码解析
AsyncSemaphore是org.redisson.pubsub包下的一个类,主要用做异步并发信号控制器,其构造函数如下
public class AsyncSemaphore {
private int counter;
private final Set<Runnable> listeners = new LinkedHashSet<Runnable>();
//传入一个int做为自己可放行的信号量
public AsyncSemaphore(int permits) {
counter = permits;
}
获取执行权限
public void acquire(Runnable listener) {
boolean run = false;
//锁的是对象本身
synchronized (this) {
//如果已经达最大执行量,把runner放入监听队列,排队执行
if (counter == 0) {
listeners.add(listener);
return;
}
//如果未达最大执行量, -1信号
if (counter > 0) {
counter--;
run = true;
}
}
//执行逻辑
if (run) {
listener.run();
}
}
释放信号
public void release() {
Runnable runnable = null;
//锁的是对象本身
synchronized (this) {
//可执行量+1
counter++;
Iterator<Runnable> iter = listeners.iterator();
//按顺序获取监听队列中的一个执行器
if (iter.hasNext()) {
runnable = iter.next();
iter.remove();
}
}
//执行监听队列中的下一个执行器
if (runnable != null) {
acquire(runnable);
}
}
使用场景
该类在redisson的使用场景处处皆是,拿ClientConnectionsEntry的构造函数举例
public ClientConnectionsEntry(RedisClient client, int poolMinSize, int poolMaxSize, int subscribePoolMinSize, int subscribePoolMaxSize,
ConnectionManager connectionManager, NodeType serverMode) {
this.client = client;
//用AsyncSemaphore管理最大链接数
this.freeConnectionsCounter = new AsyncSemaphore(poolMaxSize);
this.connectionManager = connectionManager;
this.nodeType = serverMode;
//用AsyncSemaphore管理最大订阅数
this.freeSubscribeConnectionsCounter = new AsyncSemaphore(subscribePoolMaxSize);
if (subscribePoolMaxSize > 0) {
connectionManager.getConnectionWatcher().add(subscribePoolMinSize, subscribePoolMaxSize, freeSubscribeConnections, freeSubscribeConnectionsCounter);
}
connectionManager.getConnectionWatcher().add(poolMinSize, poolMaxSize, freeConnections, freeConnectionsCounter);
}
使用方式
AsyncSemaphore虽然会把每个访问acquire叫做listener,并持有了一个名为listeners的LinkedHashSet,但是其本身并未实现监听机制,外部访问release方法来被动的触发监听
这里又要引入RPromise了, 其底层是netty实现,通过实现其operationComplete方法,在listener执行完后释放占用的资源.如ConnectionPool#createeConnection方法
private void createConnection(final boolean checkFreezed, final AtomicInteger requests, final ClientConnectionsEntry entry, final RPromise<Void> initPromise,
final int minimumIdleSize, final AtomicInteger initializedConnections) {
if ((checkFreezed && entry.isFreezed()) || !tryAcquireConnection(entry)) {
Throwable cause = new RedisConnectionException(
"Can't init enough connections amount! Only " + (minimumIdleSize - initializedConnections.get()) + " from " + minimumIdleSize + " were initialized. Server: "
+ entry.getClient().getAddr());
initPromise.tryFailure(cause);
return;
}
//👆上面代码已知clientConnectioonEntry是持有了控制链接池数量的Semaphore
//这里就是创建semaphore执行的listener
acquireConnection(entry, new Runnable() {
@Override
public void run() {
RPromise<T> promise = connectionManager.newPromise();
//创建链接的主要逻辑
createConnection(entry, promise);
//为listener执行完成后的回调
promise.addListener(new FutureListener<T>() {
@Override
public void operationComplete(Future<T> future) throws Exception {
if (future.isSuccess()) {
T conn = future.getNow();
releaseConnection(entry, conn);
}
//在这里释放Semaphore的信号量
releaseConnection(entry);
if (!future.isSuccess()) {
Throwable cause = new RedisConnectionException(
"Can't init enough connections amount! Only " + (minimumIdleSize - initializedConnections.get()) + " from " + minimumIdleSize + " were initialized. Server: "
+ entry.getClient().getAddr(), future.cause());
initPromise.tryFailure(cause);
return;
}
int value = initializedConnections.decrementAndGet();
if (value == 0) {
log.info("{} connections initialized for {}", minimumIdleSize, entry.getClient().getAddr());
if (!initPromise.trySuccess(null)) {
throw new IllegalStateException();
}
} else if (value > 0 && !initPromise.isDone()) {
if (requests.incrementAndGet() <= minimumIdleSize) {
createConnection(checkFreezed, requests, entry, initPromise, minimumIdleSize, initializedConnections);
}
}
}
});
}
});
}