限流工具类,同一时间只允许n个线程访问某资源
@startuml
skinparam classAttributeIconSize 0
class Semaphore{
}
class AbstractQueuedSynchronizer{
}
class Sync{
}
class FairSync{
}
class NonfairSync{
}
Sync <|-- FairSync
Sync <|-- NonfairSync
AbstractQueuedSynchronizer <|-- Sync
Semaphore --> Sync
@enduml
可以看出Semaphore也有公平的和非公平之分
限流,使用的公平策略
public class SemaphoreTest
{
private final static int THREAD_COUNT = 100;
private final static CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);
public static void main(String[] args) throws InterruptedException
{
Semaphore semaphore = new Semaphore(10, true);//true代表公平
for (int i = 0; i < THREAD_COUNT; i++)
{
new Thread(()->{
try
{
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "正在访问资源。。。");
TimeUnit.SECONDS.sleep(3);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
semaphore.release();
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
}
}
public Semaphore(int permits, boolean fair) {
//公平用的是FairSync
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
//Semaphore.Sync#Sync
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (;;) {
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
Sync(int permits) {
//最终就是设置了permits个信号量
setState(permits);
}
}
public void acquire() throws InterruptedException {
//AQS的acquireSharedInterruptibly
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//Semaphore.FairSync重写了tryAcquireShared
//如果信号量不够那么返回负数,这里执行doAcquireSharedInterruptibly入AQS队,并且阻塞等待唤醒
//如果信号量够的话返回>=0的数,那么调用此acquire方法的代码就可以继续执行业务代码
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
protected int tryAcquireShared(int acquires) {
for (;;) {
//如果队列中我的前面有人排队,那么返回-1
if (hasQueuedPredecessors())
return -1;
//当前的信号量
int available = getState();
//当前的信号量够不够我获取?
int remaining = available - acquires;
//<0表示不够的话返回这个数
if (remaining < 0 ||
//>=0说明够了,那么CAS修改剩余信号量
compareAndSetState(available, remaining))
return remaining;
}
}
public void release() {
//AQS的releaseShared
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
//Semaphore.Sync重写了tryReleaseShared
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//获取当前信号量
int current = getState();
//加回去
int next = current + releases;
//溢出则抛异常
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
//CAS修改信号量
if (compareAndSetState(current, next))
return true;
}
}
限流,使用的非公平策略
public class SemaphoreTest
{
private final static int THREAD_COUNT = 100;
private final static CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);
public static void main(String[] args) throws InterruptedException
{
Semaphore semaphore = new Semaphore(10);
for (int i = 0; i < THREAD_COUNT; i++)
{
new Thread(()->{
try
{
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "正在访问资源。。。");
TimeUnit.SECONDS.sleep(3);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
semaphore.release();
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
}
}
public Semaphore(int permits) {
//创建的是非公平的Sync
sync = new NonfairSync(permits);
}
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
//调用Sync
super(permits);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
Sync(int permits) {
//最终就是设置了permits个信号量
setState(permits);
}
}
public void acquire() throws InterruptedException {
//AQS的acquireSharedInterruptibly
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//Semaphore.NonfairSync重写了tryAcquireShared
//如果信号量不够那么返回负数,这里执行doAcquireSharedInterruptibly入AQS队,并且阻塞等待唤醒
//如果信号量够的话返回>=0的数,那么调用此acquire方法的代码就可以继续执行业务代码
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//当前的信号量
int available = getState();
//当前的信号量够不够我获取?
int remaining = available - acquires;
//<0表示不够的话返回这个数
if (remaining < 0 ||
//>=0说明够了,那么CAS修改剩余信号量
compareAndSetState(available, remaining))
return remaining;
}
}
public void release() {
//AQS的releaseShared
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
//Semaphore.Sync重写了tryReleaseShared
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//获取当前信号量
int current = getState();
//加回去
int next = current + releases;
//溢出则抛异常
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
//CAS修改信号量
if (compareAndSetState(current, next))
return true;
}
}