Is there an ExecutorService that uses the current thread?

What I need is a compatible way to configure whether to use the thread pool or not. Ideally, the rest of the code should not be affected at all. I could use a thread pool with 1 thread, but that is not quite what I want. Any ideas?

ExecutorService es = threads == 0 ? new CurrentThreadExecutor() : Executors.newThreadPoolExecutor(threads); // es.execute / es.submit / new ExecutorCompletionService(es) etc 
+75
java concurrency
Jul 05 '11 at 10:25
source share
6 answers

Here's a really simple implementation of Executor (not ExecutorService , mind you) that uses only the current thread. Stealing this from "Java Concurrency in Practice" (substantial read).

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

ExecutorService is a more complex interface, but it can be handled using the same approach.

+55
Jul 05 2018-11-11T00:
source share

You can use Guava MoreExecutors.newDirectExecutorService() or MoreExecutors.directExecutor() if you do not need ExecutorService .

If turning Guava on is too heavy, you can implement something almost as well:

 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. // All other submitted tasks will use the RejectedExecutionHandler // which runs tasks using the caller thread. instance.submit(new Runnable() { @Override public void run() { boolean interrupted = false; try { while (true) { try { instance.signal.await(); break; } catch (InterruptedException e) { interrupted = true; } } } finally { if (interrupted) { Thread.currentThread().interrupt(); } } }}); return Executors.unconfigurableScheduledExecutorService(instance); } } 
+74
Feb 01 '13 at 4:24
source share

Java 8 style:

Executor e = Runnable::run;

+44
Jan 19 '15 at 8:00
source share

I wrote an ExecutorService based on AbstractExecutorService .

 /** * 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(); } } 
+10
Dec 05
source share

You can use the RejectedExecutionHandler to run the task in the current thread.

 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(); } }); 

You only need one of them.

+5
Jul 05 '11 at 11:21
source share

I had to use the same "CurrentThreadExecutorService" for testing, and although all the solutions offered were good (especially mentioning the Guava path ), I came up with something similar to what Peter Laurie suggested here .

As Axelle Ziegler here mentioned, unfortunately, Peter’s solution doesn’t actually work because of the check introduced in ThreadPoolExecutor in the constructor parameter maximumPoolSize (i.e. maximumPoolSize cannot be <=0 ).

To get around this, I did the following:

 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); } }; } 
+4
Aug 28 '17 at 10:13
source share



All Articles