Utils { static <T> CompletionStage<T> onExecutor(CompletionStage<T> future, Executor executor) { if (executor == null) { return future; } return future.whenCompleteAsync((t, throwable) -> {}, executor); } private  Utils(); static int ttlToExpiration(final int ttl); static Function<List<List<T>>, List<T>> flatten(); static int getGlobalConnectionCount(); static Throwable unwrap(final Throwable e);  }
@Test public void testOnExecutorOk() throws ExecutionException, InterruptedException { ExecutorService executorA = Executors.newSingleThreadExecutor( new ThreadFactoryBuilder().setNameFormat("thread-A-%d").setDaemon(true).build()); ExecutorService executorB = Executors.newSingleThreadExecutor( new ThreadFactoryBuilder().setNameFormat("thread-B-%d").setDaemon(true).build()); CompletableFuture<String> future = new CompletableFuture<>(); CompletableFuture<String> future2 = Utils.onExecutor(future, executorB) .toCompletableFuture() .thenApply(s -> Thread.currentThread().getName()); executorA.submit( () -> { future.complete(Thread.currentThread().getName()); }); assertEquals("thread-B-0", future2.get()); }
@Test public void testOnExecutorException() throws ExecutionException, InterruptedException { ExecutorService executorA = Executors.newSingleThreadExecutor( new ThreadFactoryBuilder().setNameFormat("thread-A-%d").setDaemon(true).build()); ExecutorService executorB = Executors.newSingleThreadExecutor( new ThreadFactoryBuilder().setNameFormat("thread-B-%d").setDaemon(true).build()); CompletableFuture<String> future = new CompletableFuture<>(); CompletableFuture<String> future2 = Utils.onExecutor(future, executorB) .toCompletableFuture() .exceptionally(s -> Thread.currentThread().getName()); executorA.submit( () -> { future.completeExceptionally(new RuntimeException()); }); assertEquals("thread-B-0", future2.get()); }