WeighingDelegate (final CompletionProgressIndicator indicator) { final class WeighItems implements Runnable { @Override public void run() { try { while (true) { Computable<Boolean> next = myQueue.poll(30, TimeUnit.MILLISECONDS); if (next != null && !next.compute()) { tryReadOrCancel(indicator, () -> indicator.addDelayedMiddleMatches()); return; } indicator.checkCanceled(); } } catch (InterruptedException e) { LOG.error(e); } } } final Future<?> future = startThread(ProgressWrapper.wrap(indicator), new WeighItems()); return new WeighingDelegate() { @Override public void waitFor() { myQueue.offer(new Computable.PredefinedValueComputable<>(false)); try { future.get(); } catch (InterruptedException | ExecutionException e) { LOG.error(e); } } @Override public void consume(final CompletionResult result) { if (ourIsInBatchUpdate.get().booleanValue()) { myBatchList.add(result); } else { myQueue.offer(() -> { tryReadOrCancel(indicator, () -> indicator.addItem(result)); return true; }); } } }; }