semaphore for limiting database load. private final TimedSemaphore semaphore; // Create an instance and set the semaphore public StatisticsThread(TimedSemaphore timedSemaphore) { semaphore = timedSemaphore; } // Gather statistics public void run() { try { while(true) { semaphore.acquire(); // limit database load performQuery(); // issue a query } } catch(InterruptedException) { // fall through } } ... } The following code fragment shows how a {@code TimedSemaphore} is createdthat allows only 10 operations per second and passed to the statistics thread:
TimedSemaphore sem = new TimedSemaphore(1, TimeUnit.SECOND, 10); StatisticsThread thread = new StatisticsThread(sem); thread.start();
When creating an instance the time period for the semaphore must be specified. {@code TimedSemaphore} uses an executor service with acorresponding period to monitor this interval. The {@code ScheduledExecutorService} to be used for this purpose can be provided atconstruction time. Alternatively the class creates an internal executor service.
Client code that uses {@code TimedSemaphore} has to call the{@link #acquire()} method in aach processing step. {@code TimedSemaphore}keeps track of the number of invocations of the {@link #acquire()} method andblocks the calling thread if the counter exceeds the limit specified. When the timer signals the end of the time period the counter is reset and all waiting threads are released. Then another cycle can start.
It is possible to modify the limit at any time using the {@link #setLimit(int)} method. This is useful if the load produced by anoperation has to be adapted dynamically. In the example scenario with the thread collecting statistics it may make sense to specify a low limit during day time while allowing a higher load in the night time. Reducing the limit takes effect immediately by blocking incoming callers. If the limit is increased, waiting threads are not released immediately, but wake up when the timer runs out. Then, in the next period more processing steps can be performed without blocking. By setting the limit to 0 the semaphore can be switched off: in this mode the {@link #acquire()} method never blocks, butlets all callers pass directly.
When the {@code TimedSemaphore} is no more needed its {@link #shutdown()}method should be called. This causes the periodic task that monitors the time interval to be canceled. If the {@code ScheduledExecutorService} has beencreated by the semaphore at construction time, it is also shut down. resources. After that {@link #acquire()} must not be called any more.
@version $Id: TimedSemaphore.java 895466 2010-01-03 19:04:08Z oheger $