I am trying to implement a work queue in Java that limits the amount of work that can be taken at a time. In particular, he is trying to protect access to an external resource. My current approach is to use Semaphore and BlockingQueue so that I have something like this:
interface LimitingQueue<V> { void put(Callable<V> work); Callable<V> tryPoll(); }
It should behave as follows:
@Test public void workLimit() throws Exception { final int workQueue = 2; final LimitingQueue<Void> queue = new LimitingQueue<Void>(workQueue); queue.put(new Work());
The implementation of tryPoll() uses Semaphore#tryAcquire and, if successful, creates an anonymous Callable that wraps the call to Semaphore#release in the try/finally block around the call to work.call() .
This works, but it is somewhat unsatisfactory in that if a user of this class does work related to a particular class that implements Callable, the user does not get access to this class when viewing the result of tryPoll . Notably, tryPoll() returns a Callable<Void> , not Work .
Is there a way to achieve that effect of limiting work by providing the caller with a useful link to the work object that was sent? (Fine, to enhance a signature like LimitingQueue more like LimitingQueue<R, T extends Callable<R>> .) I can't figure out how to ensure that the semaphore is released after the work item is called without this kind of wrapping.
source share