@Test public void consumeAvailableTest() { ExecutorLimiter limiter = getLimiter(PARALLEL_COUNT, true); List<TestRunnable> runnables = new ArrayList<>(PARALLEL_COUNT); for (int i = 0; i < PARALLEL_COUNT; i++) { TestRunnable tr = new TestRunnable(); runnables.add(tr); limiter.waitingTasks.add(limiter.new LimiterRunnableWrapper(tr)); } limiter.consumeAvailable(); // should be fully consumed assertEquals(0, limiter.waitingTasks.size()); Iterator<TestRunnable> it = runnables.iterator(); while (it.hasNext()) { it.next().blockTillFinished(); // throws exception if it does not finish } }
/** * This is called once a task is ready to be executed (or if unable to execute immediately, * queued). In addition to the task itself, this function takes in any future which represents * task execution (if available, otherwise {@code null}). Passing in as a separate argument * allows us to avoid a {@code instanceof} check, but does require it to be specified for * pre-future listener completion support. * * @param task Task to be executed * @param future Future to represent task completion or {@code null} if not available */ protected void executeOrQueue(Runnable task, ListenableFuture<?> future) { if (limitFutureListenersExecution || future == null) { executeOrQueueWrapper(new LimiterRunnableWrapper(task)); } else { // we will release the limit restriction as soon as the future completes. // listeners should be invoked in order, so we just need to be the first listener here // We add a `SameThreadSubmitterExecutor` so that we get executed first as if it was async future.addListener(this::releaseExecutionLimit, SameThreadSubmitterExecutor.instance()); if (canRunTask()) { executor.execute(task); } else { addToQueue(new TransparentRunnableContainer(task)); } } }
/** * This is called once a task is ready to be executed (or if unable to execute immediately, * queued). In addition to the task itself, this function takes in any future which represents * task execution (if available, otherwise {@code null}). Passing in as a separate argument * allows us to avoid a {@code instanceof} check, but does require it to be specified for * pre-future listener completion support. * * @param task Task to be executed * @param future Future to represent task completion or {@code null} if not available */ protected void executeOrQueue(Runnable task, ListenableFuture<?> future) { if (limitFutureListenersExecution || future == null) { executeOrQueueWrapper(new LimiterRunnableWrapper(task)); } else { // we will release the limit restriction as soon as the future completes. // listeners should be invoked in order, so we just need to be the first listener here // We add a `SameThreadSubmitterExecutor` so that we get executed first as if it was async future.addListener(this::releaseExecutionLimit, SameThreadSubmitterExecutor.instance()); if (canRunTask()) { executor.execute(task); } else { addToQueue(new TransparentRunnableContainer(task)); } } }
protected DelayedExecutionRunnable(Runnable runnable) { this(new LimiterRunnableWrapper(runnable)); }
protected DelayedExecutionRunnable(Runnable runnable) { this(new LimiterRunnableWrapper(runnable)); }