CaptureObjectLoader { @NotNull public ListenableFuture<CaptureObject> loadCapture(@NotNull CaptureObject captureObject, @Nullable Range queryRange, @Nullable Executor queryJoiner) { assert myExecutorService != null; cancelTask(); ListenableFutureTask<CaptureObject> task = ListenableFutureTask.create(() -> captureObject.load(queryRange, queryJoiner) ? captureObject : null); myOutstandingLoadingTask = task; Futures.addCallback(task, new FutureCallback<CaptureObject>() { @Override public void onSuccess(@Nullable CaptureObject result) { removeTask(); } @Override public void onFailure(@NotNull Throwable ignored) { removeTask(); } private void removeTask() { myOutstandingLoadingTask = null; } }, MoreExecutors.directExecutor()); myExecutorService.execute(task); return task; }  @NotNull ListenableFuture<CaptureObject> loadCapture(@NotNull CaptureObject captureObject,
                                                     @Nullable Range queryRange,
                                                     @Nullable Executor queryJoiner); void start(); void stop();  }
@Test(expected = AssertionError.class) public void loadCaptureBeforeStart() throws Exception { TestCaptureObject capture = new TestCaptureObject(new CountDownLatch(1), true, false); myLoader.loadCapture(capture, null, null); }