packagejava.util.concurrent;importjava.util.Collection;importjava.util.concurrent.locks.AbstractQueuedSynchronizer;public class Semaphore implementsjava.io.Serializable {private static final long serialVersionUID = -3222578661600680210L;/**All mechanics via AbstractQueuedSynchronizer subclass*/
private finalSync sync;abstract static class Sync extendsAbstractQueuedSynchronizer {private static final long serialVersionUID = 1192457210091910933L;
Sync(intpermits) {
setState(permits);
}final intgetPermits() {returngetState();
}final int nonfairTryAcquireShared(intacquires) {for(;;) {int available =getState();int remaining = available -acquires;if (remaining < 0 ||compareAndSetState(available, remaining))returnremaining;
}
}protected final boolean tryReleaseShared(intreleases) {for(;;) {int current =getState();int next = current +releases;if (next < current) //overflow
throw new Error("Maximum permit count exceeded");if(compareAndSetState(current, next))return true;
}
}final void reducePermits(intreductions) {for(;;) {int current =getState();int next = current -reductions;if (next > current) //underflow
throw new Error("Permit count underflow");if(compareAndSetState(current, next))return;
}
}final intdrainPermits() {for(;;) {int current =getState();if (current == 0 || compareAndSetState(current, 0))returncurrent;
}
}
}/*** NonFair version*/
static final class NonfairSync extendsSync {private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(intpermits) {super(permits);
}protected int tryAcquireShared(intacquires) {returnnonfairTryAcquireShared(acquires);
}
}/*** Fair version*/
static final class FairSync extendsSync {private static final long serialVersionUID = 2014338818796000944L;
FairSync(intpermits) {super(permits);
}protected int tryAcquireShared(intacquires) {for(;;) {if(hasQueuedPredecessors())return -1;int available =getState();int remaining = available -acquires;if (remaining < 0 ||compareAndSetState(available, remaining))returnremaining;
}
}
}/*** Creates a {@codeSemaphore} with the given number of
* permits and nonfair fairness setting.
*
*@parampermits the initial number of permits available.
* This value may be negative, in which case releases
* must occur before any acquires will be granted.*/
public Semaphore(intpermits) {
sync= newNonfairSync(permits);
}public Semaphore(int permits, booleanfair) {
sync= fair ? new FairSync(permits) : newNonfairSync(permits);
}public void acquire() throwsInterruptedException {
sync.acquireSharedInterruptibly(1);
}public voidacquireUninterruptibly() {
sync.acquireShared(1);
}public booleantryAcquire() {return sync.nonfairTryAcquireShared(1) >= 0;
}public boolean tryAcquire(longtimeout, TimeUnit unit)throwsInterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}public voidrelease() {
sync.releaseShared(1);
}public void acquire(int permits) throwsInterruptedException {if (permits < 0) throw newIllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}public void acquireUninterruptibly(intpermits) {if (permits < 0) throw newIllegalArgumentException();
sync.acquireShared(permits);
}public boolean tryAcquire(intpermits) {if (permits < 0) throw newIllegalArgumentException();return sync.nonfairTryAcquireShared(permits) >= 0;
}public boolean tryAcquire(int permits, longtimeout, TimeUnit unit)throwsInterruptedException {if (permits < 0) throw newIllegalArgumentException();returnsync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
}public void release(intpermits) {if (permits < 0) throw newIllegalArgumentException();
sync.releaseShared(permits);
}public intavailablePermits() {returnsync.getPermits();
}public intdrainPermits() {returnsync.drainPermits();
}protected void reducePermits(intreduction) {if (reduction < 0) throw newIllegalArgumentException();
sync.reducePermits(reduction);
}public booleanisFair() {return sync instanceofFairSync;
}public final booleanhasQueuedThreads() {returnsync.hasQueuedThreads();
}public final intgetQueueLength() {returnsync.getQueueLength();
}protected CollectiongetQueuedThreads() {returnsync.getQueuedThreads();
}publicString toString() {return super.toString() + "[Permits = " + sync.getPermits() + "]";
}
}