Does it make sense to use a ThreadPool with a poolsize of just 1 to basically just recycle that one thread over and over again for different uses in the application? Rather then doing new Thread(Runnable()) etc and then letting the garbage collector handle the removal of the thread, I thought it would be more efficient to just use that one thread for different jobs that dont need to run together.
This is what I am currently doing to define 1 poolsize threadpool.
private static int poolSize = 1;
private static int maxPoolSize = 1;
private static long keepAliveTime= 10;
private static final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
There is nothing wrong with a single threaded thread pool if it fits with how you application should function. For example, in an application I work on we have a number of services where we need to ensure that data is strictly processed in order of arrival. To do this we simply execute tasks on a single threaded executor.
Also using Executors means that it is easy to adjust the thread pool parameters in the future if you need to.
With new Thread(Runnable) you can execute N threads concurrently. It may be an advantage, but it also may bring synchronization issues.
With reusing one Thread you lose the ability to execute tasks in parallel, but you are spared the sync/concurrency issues.
Defining a one-thread pool this way is perfectly compatible with modern coding standards. it has the only drawback of not letting you parallelize any fragment of yhe code. However, I guess that's what you wanted.
One of the advantage of using the ThreadPoolExecutor being that once the thread is created, it will get reused as against creation of new Thread everytime when using new Thread.
Have you tried it without a Thread ? Threads are no efficient unless really needed and you need to do a lot of I/O specific stuff in parallel. If what you are looking for is a simple internal message queue, then it is fine.
Related
When my application launches, a executor service (using Executors.newFixedThreadPool(maxThreadNum) in java.util.concurrent) object is created. When requests come, the executor service will creates threads to handle them.
Because it takes time to create threads at run time, I want to make threads available when launching application, so that when requests come, it would take less time to process.
What I did is following:
executorService = Executors.newFixedThreadPool(200);
for (int i=0; i<200; i++) {
executorService.execute(new Runnable() {
#Override
public void run() {
System.out.println("Start thread in pool " );
}
});
}
It will creates 200 threads in the executorService pool when application launches.
Just wonder is this a correct way of creating threads when application starts?
Or is there a better way of doing it?
You are missing shutdown().It is very important to shutdown the Executor service once the operation is completed. So have try,catch and Finally block
try{
executorService.execute(...);
}catach(Exception e){
...
}finally{
executorService.shutdown(); //Mandatory
}
If you can use a ThreadPoolExecutor directly rather than an ExecutorService from Executors1, then there's perhaps a more standard/supported way to start all the core threads immediately.
int nThreads = 200;
ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
executor.prestartAllCoreThreads();
The above uses prestartAllCoreThreads().
Note that, currently, the implementation of Executors.newFixedThreadPool(int) creates a ThreadPoolExecutor in the exact same manner as above. This means you could technically cast the ExecutorService returned by the factory method to a ThreadPoolExecutor. There's nothing in the documentation that guarantees it will be a ThreadPoolExecutor, however.
1. ThreadPoolExecutor implements ExecutorService but provides more functionality. Also, many of the factory methods in Executors either returns a ThreadPoolExecutor directly or a wrapper that delegates to one. Some, like newWorkStealingPool, use the ForkJoinPool. Again, the return types of these factory methods are implementation details so don't rely too much on it.
The number of threads which could run parallel depends on your processor core. Unless you have 200 cores it would be pretty useless to make a thread pool of 200.
A great way to find out how many processors cores you have is:
int cores = Runtime.getRuntime().availableProcessors();
Moreover the overhead which develops during creating a new thread and executing it is unavoidable, so unless the task is heavily computed it would not be worth to create a new single thread for this task.
But after all your code is total fine so far.
Your code is totally fine if it works for your scenario. Since we don't know your use case, only you can answer your question with enough tests and benchmark.
However, do take note that the ThreadPool will reclaim idle threads after some time. That may bite you if you don't pay attention to it.
Just wonder is this a correct way of creating threads when application
starts?
Yes. That's a correct way of creating threads.
Or is there a better way of doing it?
Maybe. Under some workloads you might want to use a Thread pool with a variable number of threads (unlike the one created by newFixedThreadPool) - one that removes from the pool threads that have been idle for some time.
When should one use singleThreadExecutor in java? Also, when should one use cachedThreadpool?
It is specified both in documentations and books that singleThreadExecutor is preferred over fixedThreadPool(1) as it would not let modification in the number of threads like the latter, but what are the scenarios in which it is advisable or use singleThreadExecutor
newSingleThreadExecutor() is good when you know that one additional thread doing jobs in background is enough in your case (means there wouldn't be lots of jobs waiting in queue). And you don't need/want to extend Thread or implement Runnable and do all job transferring stuff by yourself. Tasks are guaranteed to execute sequentially - this also may be usefull, if you know that parallel task execution may cause deadlock or data race.
cachedThreadpool() - just look into source code
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
it creates new thread on demand and keeps them idle for no longer then 1 minute. And as it's said in docs
.. These pools will typically improve the performance of programs that
execute many short-lived asynchronous tasks. Calls to execute
will reuse previously constructed threads if available. If no existing
thread is available, a new thread will be created and added to the
pool. ..
But there is no upper bound for number of threads, so I would prefer to construct pool by hands with maximumPoolSize much fewer than Integer.MAX_VALUE, e.g. 128.
In my Android project I had a lot of places where I need to run some code asynchronously (a web request, call to db etc.). This is not long running tasks (maximum a few seconds).
Until now I was doing this kind of stuff with creating a new thread, passing it a new runnable with the task. But recently I have read an article about threads and concurrency in Java and understood that creating a new Thread for every single task is not a good decision.
So now I have created a ThreadPoolExecutor in my Application class which holds 5 threads.
Here is the code:
public class App extends Application {
private ThreadPoolExecutor mPool;
#Override
public void onCreate() {
super.onCreate();
mPool = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
}
}
And also I have a method to submit Runnable tasks to the executor:
public void submitRunnableTask(Runnable task){
if(!mPool.isShutdown() && mPool.getActiveCount() != mPool.getMaximumPoolSize()){
mPool.submit(task);
} else {
new Thread(task).start();
}
}
So when I want to run an asynchronous task in my code I get the instance of App and call the submitRunnableTask method passing the runnable to it. As you can see, I also check, if the thread pool has free threads to execute my task, if not, I create a new Thread (I don't think that this will happen, but in any case... I don't want my task to wait in a queue and slow down the app).
In the onTerminate callback method of Application I shutdown the pool.
So my question is the following: Is this kind of pattern better then creating new Threads in code? What pros and cons my new approach has? Can it cause problems that I am not aware off yet? Can you advice me something better than this to manage my asynchronous tasks?
P.S. I have some experience in Android and Java, but I am far from being a concurrency guru ) So may be there are aspects that I don't understand well in this kind of questions. Any advice will be appreciated.
This answer assumes your tasks are short
Is this kind of pattern better then creating new Threads in code?
It's better, but it's still far from ideal. You are still creating threads for short tasks. Instead you just need to create a different type of thread pool - for example by Executors.newScheduledThreadPool(int corePoolSize).
What's the difference in behaviour?
A FixedThreadPool will always have a set of threads to use and if all threads are busy, a new task will be put into a queue.
A (default) ScheduledThreadPool, as created by the Executors class, has a minimum thread pool that it keeps, even when idle. If all threads are busy when a new task comes in, it creates a new thread for it, and disposes of the thread 60 seconds after it is done, unless it's needed again.
The second one can allow you to not create new threads by yourself. This behaviour can be achieved without the "Scheduled" part, but you will then have to construct the executor yourself. The constructor is
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
The various options allow you to fine-tune the behaviour.
If some tasks are long...
And I mean long. As in most of your application lifetime (Realtime 2-way connection? Server port? Multicast listener?). In that case, putting your Runnable in an executor is detrimental - standard executors are not designed to cope with it, and their performance will deteriorate.
Think about your fixed thread pool - if you have 5 long-running tasks, then any new task will spawn a new thread, completely destroying any possible gains of the pool. If you use a more flexible executor - some threads will be shared, but not always.
The rule of thumb is
If it's a short task - use an executor.
If it's a long task - make sure your executor can handle it (i.e. it either doesn't have a max pool size, or enough max threads to deal with 1 more thread being gone for a while)
If it's a parallel process that needs to always run alongside your main thread - use another Thread.
To answer your question — Yes, using Executor is better than creating new threads because:
Executor provides a selection of different thread pools. It allows re-use of already existing threads which increases performance as thread creation is an expensive operation.
In case a thread dies, Executor can replace it with a new thread without affecting the application.
Changes to multi-threading policies are much easier, as only the Executor implementation needs to be changed.
Based on the comment of Ordous I have modified my code to work with only one pool.
public class App extends Application {
private ThreadPoolExecutor mPool;
#Override
public void onCreate() {
super.onCreate();
mPool = new ThreadPoolExecutor(5, Integer.MAX_VALUE, 1, TimeUnit.MINUTES, new SynchronousQueue<Runnable>());
}
}
public void submitRunnableTask(Runnable task){
if(!mPool.isShutdown() && mPool.getActiveCount() != mPool.getMaximumPoolSize()){
mPool.submit(task);
} else {
new Thread(task).start(); // Actually this should never happen, just in case...
}
}
So, I hope this can be useful to someone else, and if more experienced people have some comments on my approach, I will very appreciate their comments.
Some questions about Executors best usage for memory and time performance:
Is there any cost penalty incurred for the use of
ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(callable)
e.shutdown()
compared to:
new Thread(runnable).start()
If a Callable is not a long one, and never won't be more than one instance running of it it's ok to use the code from (1)? Or is it best to have ExecutorService as a static instance and reuse between calls?
If I have several tasks as described in (2) is there any problem with every task to having its own executor service or is better to have a centralized one? (I'm talking about a client application where normally there won't be more than one of these tasks running)
What resources does an Executor consume if it isn't shutdown()?
Is there any cost penalty from using
ExecutorService e=Executors.newSingleThreadExecutor();
e.execute(callable)
e.shutdown()
compared to:
new Thread(runnable).start()
Yes, there is a "penalty": the ExecutorService will most likely be more expensive to create since it also creates a queue for the tasks you're submitting and if a thread fails prior to shutdown, then the failed thread will be replaced with another one in order to run any subsequent tasks (so there is quite a bit of logic there). However, you probably don't want to be creating an ExecutiveService each time you want to run a task... that's probably not the best use of an ExecutorService (more on that in the next question).
If a Callable is not a long one, and never won't be more than one instance running of it it's ok to use the code from -1-? Or it's best to have ExecutorService as static one and reuse between calls?
The suggested use of the ExecutorService is as a thread pool, where you keep the ExecutorService around and you keep submitting tasks to it as long as you have tasks to submit. It can be static or just a regular member, that is irrelevant and highly dependent on your requirements/design. Even if you're only running one instance at a time (i.e. you only have a single-threaded executor), it's still more efficient to use the ExecutorService because it reuses the thread, so in the long run it will be less expensive than creating a new thread for each task you submit.
If I have several task... is there any problem for every task to have their executor service or is better to have a centralized one?
There is no problem, but it's inefficient, so just have a centralized executor service.
What resources consumes an Executor if it isn't shutdown()?
I don't think you should worry about that in particular, especially if you're using the Executor in the correct context it will be minimal.
The point of an ExecutorService is to share many tasks among a fixed number of threads. Creating an ExecutorService to run a single task is wasteful overhead.
new Thread(runnable).start() should always be faster than creating an ExecutorService as the ExecutorService will just create the thread anyway, but with the added overhead of keeping track of it.
Well title says it, what is the difference between Executors.newSingleThreadExecutor().execute(command) and new Thread(command).start();
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.
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.
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.
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.
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)
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).