package com.equalexperts.logging.impl; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; /** * Like an {@link java.util.concurrent.Executor Executor}, except that the execute method * returns a {@link java.util.concurrent.Future Future}, and execution is guaranteed to be * executed asynchronously. * * Spawns a new thread when @{link execute execute} is called, and the various methods of the * Future can be used to control the thread or wait for it to finish. * * This is more testable than directly manipulating threads ({@link java.lang.Thread Thread} * has final methods that can't be intercepted by normal mocking libraries), and is easier than * dealing with a full {@link java.util.concurrent.ExecutorService ExecutorService}, which has to be * stopped and is perhaps more useful with a stream of small tasks than a single long-running one. * * @see java.util.concurrent.Executor * @see java.util.concurrent.Future */ public class AsyncExecutor { private final ThreadFactory factory; public AsyncExecutor(ThreadFactory factory) { this.factory = factory; } public Future<?> execute(Runnable runnable) { CompletableFuture<?> result = new CompletableFuture<Object>() { @Override public boolean cancel(boolean mayInterruptIfRunning) { throw new UnsupportedOperationException("Calling thread.stop is deprecated. Arrange termination directly with the runnable"); } }; factory.newThread(() -> { try { runnable.run(); } finally { result.complete(null); } }).start(); return result; } }