是否有使用当前线程的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实际上并不能正常工作,因为ThreadPoolExecutor
在maximumPoolSize
构造函数参数(即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); } }; }