是否有使用当前线程的ExecutorService?

我所追求的是一种兼容的方式来configuration使用线程池或不使用。 理想情况下,其他代码不应该受到影响。 我可以使用1个线程的线程池,但这不是我想要的。 有任何想法吗?

ExecutorService es = threads == 0 ? new CurrentThreadExecutor() : Executors.newThreadPoolExecutor(threads); // es.execute / es.submit / new ExecutorCompletionService(es) etc 

这是一个非常简单的Executor (不是ExecutorService ,介意你)的实现,只使用当前线程。 从“Java并发实践”中窃取这个(必读)。

 public class CurrentThreadExecutor implements Executor { public void execute(Runnable r) { r.run(); } } 

ExecutorService是一个更复杂的接口,但可以用相同的方法处理。

如果您不需要ExecutorService ,则可以使用Guava的MoreExecutors.newDirectExecutorService()MoreExecutors.directExecutor()

如果包括番石榴太重,你可以实现一些东西几乎一样好:

 public final class SameThreadExecutorService extends ThreadPoolExecutor { private final CountDownLatch signal = new CountDownLatch(1); private SameThreadExecutorService() { super(1, 1, 0, TimeUnit.DAYS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); } @Override public void shutdown() { super.shutdown(); signal.countDown(); } public static ExecutorService getInstance() { return SingletonHolder.instance; } private static class SingletonHolder { static ExecutorService instance = createInstance(); } private static ExecutorService createInstance() { final SameThreadExecutorService instance = new SameThreadExecutorService(); // The executor has one worker thread. Give it a Runnable that waits // until the executor service is shut down. instance.submit(new Runnable() { @Override public void run() { try { instance.signal.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }}); return Executors.unconfigurableScheduledExecutorService(instance); } } 

Java 8风格:

Executor e = Runnable::run;

我写了一个基于AbstractExecutorService的ExecutorService。

 /** * Executes all submitted tasks directly in the same thread as the caller. */ public class SameThreadExecutorService extends AbstractExecutorService { //volatile because can be viewed by other threads private volatile boolean terminated; @Override public void shutdown() { terminated = true; } @Override public boolean isShutdown() { return terminated; } @Override public boolean isTerminated() { return terminated; } @Override public boolean awaitTermination(long theTimeout, TimeUnit theUnit) throws InterruptedException { shutdown(); // TODO ok to call shutdown? what if the client never called shutdown??? return terminated; } @Override public List<Runnable> shutdownNow() { return Collections.emptyList(); } @Override public void execute(Runnable theCommand) { theCommand.run(); } } 

您可以使用RejectedExecutionHandler在当前线程中运行任务。

 public static final ThreadPoolExecutor CURRENT_THREAD_EXECUTOR = new ThreadPoolExecutor(0, 0, 0, TimeUnit.DAYS, new SynchronousQueue<Runnable>(), new RejectedExecutionHandler() { public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { r.run(); } }); 

你只需要其中的一个。

为了testing目的,我必须使用相同的“CurrentThreadExecutorService”,尽pipe所有build议的解决scheme都很好(特别是提到了番石榴的方法 ),但我想出了一些类似于Peter Lawrey 在此提出的内容。

正如Axelle Ziegler 在这里提到的,不幸的是,Peter的解决scheme实际上并不能正常工作,因为ThreadPoolExecutormaximumPoolSize构造函数参数(即maximumPoolSize不能<=0 )中引入了检查。

为了规避这一点,我做了以下几点:

 private static ExecutorService currentThreadExecutorService() { CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy(); return new ThreadPoolExecutor(0, 1, 0L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), callerRunsPolicy) { @Override public void execute(Runnable command) { callerRunsPolicy.rejectedExecution(command, this); } }; }