1

In Java, both of the following code snippets can be used to quickly spawn a new thread for running some task-

This one using Thread-

new Thread(new Runnable() {
    @Override
    public void run() {
        // TODO: Code goes here
    }
}).start();

And this one using Executor-

Executors.newSingleThreadExecutor().execute(new Runnable(){
    @Override
    public void run() {
        // TODO: Code goes here
    }
});

Internally, what is the difference between this two codes and which one is a better approach?
Just in case, I'm developing for Android.


Now I think, I was actually looking for use-cases of newSingleThreadExecutor(). Exactly this was asked in this question and answered-
Examples of when it is convenient to use Executors.newSingleThreadExecutor()

Community
  • 1
  • 1
Gulshan
  • 3,611
  • 5
  • 35
  • 46
  • SingleThreadExecutor should be used when you need an Executor and you want only one thread. If you want to run just one task just once and you don't need any other Executor characteristic you are free to choose. Executors for example give you a Future for a Callable. – aalku Jun 11 '15 at 14:17

4 Answers4

2

Your second example is strange, creating an executor just to run one task is not a good usage. The point of having the executor is so that you can keep it around for the duration of your application and submit tasks to it. It will work but you're not getting the benefits of having the executor.

The executor can keep a pool of threads handy that it can reuse for incoming tasks, so that each task doesn't have to spin up a new thread, or if you pick the singleThread one it can enforce that the tasks are done in sequence and not overlap. With the executor you can better separate the individual tasks being performed from the technical implementation of how the work is done.

With the first approach where you create a thread, if something goes wrong with your task in some cases the thread can get leaked; it gets hung up on something, never finishes its task, and the thread is lost to the application and anything else using that JVM. Using an executor can put an upper bound on the number of threads you lose to this kind of error, so at least your application degrades gracefully and doesn't impair other applications using the same JVM.

Also with the thread approach each thread you create has to be kept track of separately (so that for instance you can interrupt them once it's time to shutdown the application), with the executor you can shut the executor down once and let it handle its threads itself.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • I never saw the second example anywhere and just made it up. And it worked. So, I wondered, if it is somehow better than the quick thread creation approach, which(or something similar) I have seen many times as an example. – Gulshan Jun 11 '15 at 13:57
1

The second using an ExecutorService is definitely the best approach.

ExecutorService determines how you want your tasks to run concurrently. It decouples the Runnables (or Callables) from their execution.

When using Thread, you couple the tasks with how you want them to be executed, giving you much less flexibility.

Also, ExecutorService gives you a better way of tracking your tasks and getting a return value with Future while the start method from Thread just run without giving any information. Thread therefore encourages you to code side-effects in the Runnable which may make the overall execution harder to understand and debug.

Also Thread is a costly resource and ExecutorService can handle their lifecycle, reusing Thread to run a new tasks or creating new ones depending on the strategy you defined. For instance: Executors.newSingleThreadExecutor(); creates a ThreadPoolExecutor with only one thread that can sequentially execute the tasks passed to it while Executors.newFixedThreadPool(8)creates a ThreadPoolExecutor with 8 thread allowing to run a maximum of 8 tasks in parallel.

Jean Logeart
  • 52,687
  • 11
  • 83
  • 118
1

You already have three answers, but I think this question deserves one more because none of the others talk about thread pools and the problem that they are meant to solve.

A thread pool (e.g., java.util.concurrent.ThreadPoolExecutor) is meant to reduce the number of threads that are created and destroyed by a program.

Some programs need to continually create and destroy new tasks that will run in separate threads. One example is a server that accepts connections from many clients, and spawns a new task to serve each one.

Creating a new thread for each new task is expensive; In many programs, the cost of creating the thread can be significantly higher than the cost of performing the task. Instead of letting a thread die after it has finished one task, wouldn't it be better to use the same thread over again to perform the next one?

That's what a thread pool does: It manages and re-uses a controlled number of worker threads, to perform your program's tasks.


Your two examples show two different ways of creating a single thread that will perform a single task, but there's no context. How much work will that task perform? How long will it take?

The first example is a perfectly acceptable way to create a thread that will run for a long time---a thread that must exist for the entire lifetime of the program, or a thread that performs a task so big that the cost of creating and destroying the thread is not significant.

Your second example makes no sense though because it creates a thread pool just to execute one Runnable. Creating a thread pool for one Runnable (or worse, for each new task) completely defeats the purpose of the thread-pool which is to re-use threads.


P.S.: If you are writing code that will become part of some larger system, and you are worried about the "right way" to create threads, then you probably should also learn what problem the java.util.concurrent.ThreadFactory interface was meant to solve.

Google is your friend.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • The task I am running now is short-lived network and database operation, which be invoked may be once or twice during app lifetime in Android. I had to put it off from the UI thread. Both of the way worked. People tend to recommend `Executor` in place of running raw threads. And the provided static `newSingleThreadExecutor()` method was meant for creating a single worker thread. That's why I used it. If the standard library is providing something, there should be some use-case, I thought. May be I am missing the intention of providing the method? – Gulshan Jun 12 '15 at 14:34
  • I found this SO answer very much helpful regarding use-case of `newSingleThreadExecutor`- http://stackoverflow.com/a/16814620/97714 – Gulshan Jun 12 '15 at 14:44
  • 1
    @Gulshan, `Executors.newSingleThreadExecutor()` is a convenient way to create a thread pool that has just one worker thread. It would be used by a program that spawns a sequence of "background tasks" that must be performed in strict FIFO order with respect to each other, but in parallel with whatever the rest of the program is doing. – Solomon Slow Jun 15 '15 at 13:47
0

According to documentation of ThreadPoolExecutor

Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks. Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks.

First approach is suitable for me if I want to spawn single background processing and for small applications.

I will prefer second approach for controlled thread execution environment. If I use ThreadPoolExecutor, I am sure that 1 thread will be running at time , even If I submit more threads to executor. Such cases are tend to happen if you consider large enterprise application, where threading logic is not exposed to other modules. In large enterprise application , you want to control the number of concurrent running threads. So second approach is more pereferable if you are designing enterprise or large scale applications.

Sagar Gandhi
  • 925
  • 6
  • 20