Well title says it, what is the difference between Executors.newSingleThreadExecutor().execute(command)
and new Thread(command).start();

- 398,947
- 96
- 818
- 769
6 Answers
Behaviourally, pretty much nothing.
However, once you have an Executor
instance, you can submit multiple tasks to it, and have them executed one after another. You can't do that simply with a raw Thread
.

- 398,947
- 96
- 818
- 769
-
1"Behaviourally, pretty much nothing." is totally wrong statement. There is huge behavioral difference. See my answer below – Junaed May 10 '21 at 09:05
-
What about reuse of thread vs creating multiple threads? – Gaurav Singla May 25 '21 at 10:17
One noticeable difference, is when you run new Thread(someRunnable).start();
when the runnable is finished the thread will die quietly.
The Executor though will persist until you shut it down. So running Executors.newSingleThreadExecutor().execute(command)
When you think your application or the JVM may be finished the Executor may still be running in a background thread.

- 39,695
- 7
- 78
- 108
-
1Apparently not the case: https://www.farside.org.uk/201309/learning_from_bad_code – assylias Jun 17 '16 at 07:56
-
Interesting, I can't argue with much of what he says. I can't recreate the `finalize` call after the `submit` completes. I ran a simple `main` Test and the delegating TPE is never GC'd. – John Vint Jun 17 '16 at 12:58
-
-
why do you mention the JVM? if the JVM is dead, there is no process, hence no application, hence no thread or executor. – cesarmax Jun 06 '23 at 19:16
With Executor.execute
, if an Error
or RuntimeException
is thrown in the Executor
it will be swallowed silently, while the new Thread()
will print it to System.err
.

- 11,553
- 8
- 64
- 88

- 525,659
- 79
- 751
- 1,130
-
5One solution, to avoid having exceptions swallowed by the executor, is to call `Executor.submit` instead of `execute`, then call `get` on the resulting `Future` when you want to handle the potential errors. – Lii Feb 11 '19 at 15:43
-
There can be many differences, but I will show you one difference which I found very important to understand:
public void sendEventSingleThreadExecutor(Event e){
Executor.singleThreadExecutor().execute(()->{//send the event here})
}
Now, even if you call sendEventSingleThreadExecutor method 10 times, it will use only a single thread to send them. It will not create a new thread every time. Which means that the events will be sent sequentially or synchronously! You can read more from here:
Now see the below example with new thread
public void sendEventThread(Event e){
Thread(//send the event here).start();
}
If you call it 10 times, it will create 10 new threads. Which means, the executions will be asynchronous! And it could be dangerous, it can create a lot of threads depending on how many times you call sendEventThread functions.
Please note that, the code are only for demonstration purpose, it might have syntax error! If you find any wrong description here, I will be happy to be corrected.
Some more information from here
newSingleThreadExecutor. A single-threaded executor creates a single worker thread to process tasks, replacing it if it dies unexpectedly. Tasks are guaranteed to be processed sequentially according to the order imposed by the task queue (FIFO, LIFO, priority order).[4]
[4] Single-threaded executors also provide sufficient internal synchronization to guarantee that any memory writes made by tasks are visible to subsequent tasks; this means that objects can be safely confined to the “task thread” even though that thread may be replaced with another from time to time.

- 1,457
- 13
- 15
I prefer to use ExecutorService
or ThreadPoolExecutor
even for single digit threads. They offer more flexibility.
Have a look at ExecutorService
& ThreadPoolExecutor
sections in related SE questions :
java Fork/Join pool, ExecutorService and CountDownLatch
Java's Fork/Join vs ExecutorService - when to use which?
Assume that you have started with your own thread instead of ExecutorService
. In future, if there is a need for supporting multiple threads, ExecutorService
or ThreadPoolExecutor
will offer better control and flexibility for you. You can fine-tune required number of parameters in these below APIs.
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)

- 1
- 1

- 37,698
- 11
- 250
- 211
Executors.newSingleThreadExecutor().execute(command) will reuse previously constructed thread, it will not created new thread as in case of new Thread(). If the thread that have not been used for sixty seconds are terminated, It's a kind of pool which contains a single thread which make its equivalent newFixedThreadPool(1).

- 19
- 2