public Object getItem()throws InterruptedException { available.acquire(); return getNextAvailableItem(); }
publicvoidputItem(Object x) { if (markAsUnused(x)) available.release(); }
// Not a particularly efficient data structure; just for demo
protected Object[] items = newObject[]{};//... whatever kinds of items being managed.存放ok protectedboolean[] used = newboolean[MAX_AVAILABLE];
protectedsynchronized Object getNextAvailableItem() { for (inti=0; i < MAX_AVAILABLE; ++i) { if (!used[i]) { used[i] = true; return items[i]; } } returnnull; // not reached }
protectedsynchronizedbooleanmarkAsUnused(Object item) { for (inti=0; i < MAX_AVAILABLE; ++i) { if (item == items[i]) { if (used[i]) { used[i] = false; returntrue; } else returnfalse; } } returnfalse; } }
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 {@link #acquire} is calledas 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.
/** * Acquires and returns all permits that are immediately available. * @return the number of permits acquired */ publicintdrainPermits() { return sync.drainPermits(); }
/** * Shrinks the number of available permits by the indicated reduction. * This method can be useful in subclasses that use semaphores to track resources that become unavailable. * This method differs from {@code acquire} in that it does not block waiting for permits to become available. * @param reduction the number of permits to remove * @throws IllegalArgumentException if {@code reduction} is negative */ protectedvoidreducePermits(int reduction) { if (reduction < 0) thrownewIllegalArgumentException(); sync.reducePermits(reduction); } }