Before obtaining an item each thread must acquire a permit from the semaphore, guaranteeing that an item is available for use.
When the thread has finished with the item it is returned back to the pool and a permit is returned to the semaphore, allowing
another thread to acquire that item. Note that no synchronization lock is held when acquire()
is called as that would prevent an
item from being returned to the pool. The semaphore encapsulates the synchronization needed to restrict access to the pool,
separately from any synchronization needed to maintain the consistency of the pool itself.
A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual
exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available,
or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock
implementations),
that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be
useful in some specialized contexts, such as deadlock recovery.
场景:20个人需要买票,但只有2个窗口
问题:如何控制同一时间并发数为2 ?
public class SemaphoreDemo { class SemaphoreRunnable implements Runnable{ private Semaphore semaphore; private int user; public SemaphoreRunnable(Semaphore semaphore, int user) { this.semaphore = semaphore; this.user = user; } @Override public void run() { try { semaphore.acquire(); //不能使用semaphore.tryAcquire(); System.out.printf("用户[%s]进入窗口 ", user ); Thread.sleep((long) (Math.random()*10000)); System.out.printf("用户[%s]离开窗口 ", user ); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } private void exec(){ Semaphore semaphore = new Semaphore(2); ExecutorService executorService = Executors.newCachedThreadPool(); for(int i=0; i<20; i++){ executorService.execute(new SemaphoreRunnable(semaphore, i)); } } public static void main(String[] args){ SemaphoreDemo demo = new SemaphoreDemo(); demo.exec(); } }