直接上源碼,註釋分析:
package com.play.english.tomcat.thread;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* @author chaiqx on 2020/5/25
*/
public class LimitLatch {
private final Sync sync;//線程同步器
private final AtomicLong count;//當前連接數目
private volatile long limit;//最大限制連接數
private volatile boolean released;//是否線程全部釋放
/**
* 繼承的AQS
* AQS其實就是一個框架,具體需要我們去控制線程的阻塞和喚醒
*/
private class Sync extends AbstractQueuedSynchronizer {
public Sync() {
}
/**
* 主要是判斷是否達到最大限制數
* <p>
* 如果超過最大限制數的話返回-1 否則返回1
* <p>
* 其實最後主要用來AQS的線程是否阻塞判斷
*
* @param args
* @return
*/
@Override
protected int tryAcquireShared(int args) {
long newCount = count.incrementAndGet(); //加入一個連接之後的連接數目
if (!released && newCount > limit) {//不是所有線程喚醒並且已經大於最大限制數
count.decrementAndGet();//把自己的該1個連接數目去掉
return -1;//返回-1表示該線程將要進入阻塞
} else {
return 1;//返回1表示該線程直接通過不用阻塞
}
}
/**
* 主要是釋放連接數
*
* @param args
* @return
*/
@Override
protected boolean tryReleaseShared(int args) {
count.decrementAndGet();//釋放1個連接
return true;
}
}
/**
* 構造函數
* <p>
* 初始化私有變量
*
* @param limit
*/
public LimitLatch(long limit) {
this.limit = limit;
this.count = new AtomicLong(0);
this.sync = new Sync();
}
/**
* 調用這個用來進行線程的阻塞
* <p>
* 如果當前連接數已經滿了,則線程進行循環阻塞
*
* @throws InterruptedException
*/
public void countUpOrAwait() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* 釋放一個連接
* <p>
* 喚醒一個線程
*
* @return
*/
public long countDown() {
sync.releaseShared(0);
return getCount();
}
/**
* 喚醒所有的線程
* <p>
* 釋放一個連接
*
* @return
*/
public boolean releaseAll() {
released = true;
return sync.releaseShared(0);
}
/**
* 重置連接限制器
*/
public void reset() {
this.count.set(0);
released = false;
}
/**
* 獲取當前連接數目
*
* @return
*/
public long getCount() {
return count.get();
}
}