@Override
  @SuppressWarnings("FutureReturnValueIgnored")
  public void loadAll(Set<? extends K> keys, boolean replaceExistingValues,
      CompletionListener completionListener) {
    requireNotClosed();
    keys.forEach(Objects::requireNonNull);
    CompletionListener listener = (completionListener == null)
        ? NullCompletionListener.INSTANCE
        : completionListener;

    if (cacheLoader.isEmpty()) {
      listener.onCompletion();
      return;
    }

    var future = CompletableFuture.runAsync(() -> {
      try {
        if (replaceExistingValues) {
          loadAllAndReplaceExisting(keys);
        } else {
          loadAllAndKeepExisting(keys);
        }
        listener.onCompletion();
      } catch (CacheLoaderException e) {
        listener.onException(e);
      } catch (RuntimeException e) {
        listener.onException(new CacheLoaderException(e));
      } finally {
        dispatcher.ignoreSynchronous();
      }
    }, executor);

    inFlight.add(future);
    future.whenComplete((r, e) -> inFlight.remove(future));
  }
@Test
  public void load_cacheLoaderException() {
    var e = new CacheLoaderException();
    CompletionListener completionListener = Mockito.mock();
    doThrow(e).when(completionListener).onCompletion();
    jcache.loadAll(keys, true, completionListener);
    verify(completionListener).onException(e);
  }