Will a ScheduledExecutorService create new threads as needed? - java

I'm using Executors.newScheduledThreadPool() to create a ScheduledExecutorService, specifying the number of threads like so:
int corePoolSize = 42;
ScheduledExecutorService foo = Executors.newScheduledThreadPool(corePoolSize);
According to the JavaDocs, the corePoolSize argument sets
the number of threads to keep in the pool, even if they are idle.
Does this mean that this ExecutorService implementation may create more than corePoolSize threads as needed, similar to a cached thread pool?

No. The correct answer is no, a ScheduledExecutorService will not spawn new threads.
See answer here

Does this mean that this ExecutorService implementation may create more than corePoolSize threads as needed?
Yes, that is exactly what it means. The reason for the existence of corePoolSize is the expense of thread-creation. If you expect to be firing large numbers of short-lived tasks at your executor service, you may expect to find, at a given point in time, large numbers of idle threads.
Rather than have these threads die, only to be replaced a very short time later by newly-created threads, corePoolSize will ensure that there will always be a number of spinning threads.

Related

Changing Fixed Threadpool max pool size

At the moment I'm creating fixed thread pool using the Executor service like
executor = Executors.newFixedThreadPool(coreAmount);
While this is fine, I was wondering if it's possible to keep the behaviour of creating a number of threads and change the max pool limit so that if all the threads are in use to create a new thread and use it instead of waiting for one of the threads to terminate to start.
So for example if 8 threads are created and are being used, 9th task enters I want it to create a new thread in addition to the 8 currently in use.
It seems newCachedThreadPool() has the behaviour but I also want the ability to create number of threads similar to newFixedThreadPool(int nThreads)
Maybe you can use the ThreadPoolExecutor class. It is an ExecutorService and has the concept of core pool count and max pool count. It also has other features that make it more customizable than the Objects returned by Executors.
Below is an example.
int coreAmount = 8;
ExecutorService executor;
//executor = Executors.newFixedThreadPool(coreAmount);
int overrun = 4;
int maxWorkCount = 1_000;
executor = new ThreadPoolExecutor(coreAmount, coreAmount + overrun, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(maxWorkCount));
Here is more info about the params passed in the constructor in the example above.
corePoolSize - the number of
threads to keep in the pool, even if they are idle, unless
allowCoreThreadTimeOut is set
maximumPoolSize - the maximum number of
threads to allow in the pool
keepAliveTime - when the number of
threads is greater than the core, this is the maximum time that excess
idle threads will wait for new tasks before terminating.
unit - the time unit for the keepAliveTime argument
workQueue - the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
Like you said, a cached thread pool is exactly what you're looking for. From it's documentation,
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. 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. Threads that have not been used for sixty seconds are terminated and removed from the cache. Thus, a pool that remains idle for long enough will not consume any resources.
(Emphasis: mine)
So for example if 8 threads are created and are being used, 9th task enters I want it to create a new thread in addition to the 8 currently in use.
This is exactly the case with Executors#newCachedThreadPool, as seen from its documentation above.
Here is what you can use if you want to emulate a cached thread pool, but with a minimum amount of 8 threads:
ExecutorService service = new ThreadPoolExecutor(8, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
This is available in the ThreadPoolExecutor using Core Pool & Maximum Pool size values:
From the javadoc, you can see that:
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool.
By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks.
Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize(int) and setMaximumPoolSize(int).
So, in your example, you would need to set the 'corePoolSize' to the value of 8. You would then need to set the 'maximumPoolSize' which would then serve as the upper-bound to the pool.
Also, as in the javadoc, these values can be altered dynamically.

Java ThreadPoolExecutor and BlockingQueue to be used

In the Oracle site (http://docs.oracle.com/javase/7/docs/api/?java/util/concurrent/ThreadPoolExecutor.html) under Queuing section, its mentioned that "If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread."
Lot of our code have corePoolSize as 1 and maximumPoolSize are like 10 or 20.
(1) Is it a bad practice? or rather not an optimal way to use ThreadPool's?
(2) Would you recommend have corePoolSize and maximumPoolSize value be same when creating a ThreadPoolExecutor?
Another question is with respect to usage of a BlockingQueue while creating a ThreadPoolExecutor - between LinkedBlockingQueue or ConcurrentLinkedQueue? I was looking more from the locking and performance point-of-view? Though running a test proves, inserting in a concurrentLinkedQueue is quite fast compared to other. Any thoughts?
Edited:
The first part has been answered in various questions. The one I liked
How to get the ThreadPoolExecutor to increase threads to max before queueing?
Please find the bellow points .
If a new task is submitted to the list of tasks to be executed, and
less than corePoolSize threads are running, a new thread is created
to handle the request. Incoming tasks are queued in case
corePoolSize or more threads are running.
If a request can’t be queued or there are less than corePoolSize
threads running, a new thread is created unless this would exceed
maximumPoolSize.
If the pool currently has more than corePoolSize threads, excess
threads will be terminated if they have been idle for more than the
keepAliveTime.
If a new task is submitted to the list of tasks to be executed and
there are more than corePoolSize but less than maximumPoolSize
threads running, a new thread will be created only if the queue is
full. This means that when using an Unbounded queue, no more threads
than corePoolSize will be running and keepAliveTime has no
influence.
If corePoolSize and maximumPoolSize are the same, a fixed-size
thread pool is used
Your ThreadPool Size
Core Pool size is 1.
Max Pool size is 10 or 20.
Question 1 : Is it a bad practice? or rather not an optimal way to use ThreadPool's?
It is based on your Pool which is used.
If you are using bounded queue , new thread will be created upto max size once it reaches the max limit of bounded queue. Otherwise it will run in core pool size . If you are using unbounded queue it will be Core pool size only.
Question 2 : Would you recommend have corePoolSize and maximumPoolSize value be same when creating a ThreadPoolExecutor?
Yes. So that only you can get same no of threads instead of what kind blocking queue . Even non blocking queue also you can get max no of threads.
Question 3 concurrentLinkedQueue vs LinkedBlockingQueue
You should not allow to use concurrentLinkedQueue since threadpool only supports BlockingQueue. So you may try concurrentLinkedBlockingQueue. Because concurrentLinkedBlockingQueue is unbounded. But LinkedBlockingQueue is bounded.
Well that should not happen, the reason TPE puts the request(Runnable) in queue is that it should not consume too much memory. But it guarantees the execution of all Runnables.
The purpose of thread pool executor is to optimize Memory.
If you want to increase pool size to max before adding in queue then I think you would have to extend the Thread Pool Executor.

meaning of 'core pool size' in ScheduledThreadPoolExecutor's constructor

I'm new to ScheduledThreadPoolExecutor (as I usually use the simple Timer, but people have been advising against it), and I don't quite understand what would be the appropriate integer value to pass to the ScheduledThreadPoolExecutor(int) constructor.
Could anyone explain this?
Thank you
In case of ScheduledThreadPoolExecutor, corePoolSize is maximum number of threads that will be created to perform scheduled actions.
This thread pool is fixed-sized and idle threads are kept alive.
DrunkenRabbit's answer is simply ivalid because ScheduledThreadPoolsExecutor docs says explicitly that (There will be no thread count spikes at all):
While this class inherits from ThreadPoolExecutor, a few of the
inherited tuning methods are not useful for it. In particular, because
it acts as a fixed-sized pool using corePoolSize threads and an
unbounded queue, adjustments to maximumPoolSize have no useful effect.
Now as for the value, reasonable number would be number of CPU cores that application is running on.
Essentially, the corePoolSize is the number of Threads to maintain in the pool.
eg. if you expect 10 concurrent requests on a regular basis, but peaks of 20. The corePoolSize should be 10 and max as 20. This way the executor will create up to 10 new threads, even if idle threads are available for use.
As stated in the JavaDocs
Core and maximum pool sizes
A ThreadPoolExecutor will automatically adjust the pool size (see getPoolSize()) according to the bounds set by corePoolSize (see getCorePoolSize()) and maximumPoolSize (see getMaximumPoolSize()). When a new task is submitted in method execute(java.lang.Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full. By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize(int) and setMaximumPoolSize(int).

ThreadPoolExecutor with unbounded queue not creating new threads

My ThreadPoolExecutor is failing to create new threads. In fact I wrote a somewhat hacky LinkedBlockingQueue that will accept any task (i.e. it is unbounded) but call an additional handler - which in my application spews warning trace that the pool is behind - which gives me very explicit information that the TPE is refusing to create new threads even though the queue has thousands of entries in it. My constructor is as follows:
private final ExecutorService s3UploadPool =
new ThreadPoolExecutor(1, 40, 1, TimeUnit.HOURS, unboundedLoggingQueue);
Why is it not creating new threads?
This gotcha is covered in this blog post:
This construction of thread pool will simply not work as expected. This is due to the logic within the ThreadPoolExecutor where new threads are added if there is a failure to offer a task to the queue. In our case, we use an unbounded LinkedBlockingQueue, where we can always offer a task to the queue. It effectively means that we will never grow above the core pool size and up to the maximum pool size.
If you also need to decouple the minimum from maximum pool sizes, you will have to do some extended coding. I am not aware of a solution that exists in the Java libraries or Apache Commons. The solution is to create a coupled BlockingQueue that is aware of the TPE, and will go out of its way to reject a task if it knows the TPE has no threads available, then manually requeue. It is covered in more detail in linked post. Ultimately your construction will look like:
public static ExecutorService newScalingThreadPool(int min, int max, long keepAliveTime) {
ScalingQueue queue = new ScalingQueue();
ThreadPoolExecutor executor =
new ScalingThreadPoolExecutor(min, max, keepAliveTime, TimeUnit.MILLISECONDS, queue);
executor.setRejectedExecutionHandler(new ForceQueuePolicy());
queue.setThreadPoolExecutor(executor);
return executor;
}
However more simply set corePoolSize to maxPoolSize and don't worry about this nonsense.
There is a workaround to this problem. Consider the following implementation:
int corePoolSize = 40;
int maximumPoolSize = 40;
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.allowCoreThreadTimeOut(true);
By setting the allowCoreThreadTimeOut() to true, the threads in the pool are allowed to terminate after the specified timeout (60 seconds in this example). With this solution, it is the corePoolSize constructor argument that determines the maximum pool size in practice, because the thread pool will grow up to the corePoolSize, and then start adding jobs to the queue. It is likely that the pool may never grow bigger than that, because the pool will not spawn new threads until the queue is full (which, given that the LinkedBlockingQueue has an Integer.MAX_VALUE capacity may never happen). Consequently, there is little point in setting maximumPoolSize to a larger value than corePoolSize.
Consideration: The thread pool have 0 idle threads after the timeout has expired, which means that there will be some latency before the threads are created (normally, you would always have corePoolSize threads available).
More details can be found in the JavaDoc of ThreadPoolExecutor.
As mentioned by #djechlin, this is part of the (surprising to many) defined behavior of the ThreadPoolExecutor. I believe I've found a somewhat elegant solution around this behavior that I show in my answer here:
How to get the ThreadPoolExecutor to increase threads to max before queueing?
Basically you extend LinkedBlockingQueue to have it always return false for queue.offer(...) which will add an additional threads to the pool, if necessary. If the pool is already at max threads and they all are busy, the RejectedExecutionHandler will be called. It is the handler which then does the put(...) into the queue.
See my code there.

ThreadPoolExecutor on java doc

at http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
you can read the description of parameters to constructor.
Specifically in the "Core and maximum pool sizes" paragraph, it's written:
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
...
By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks.
Now I can't understand what "only if the queue is full" in the first part stands for...
Will ThreadPoolExecutor wait until queue is full or it will simply create a new worker?
An suppose now that we have more tasks that aren't asynchronous between them: using a ThreadPoolExecutor could cause a deadlock? Supposing that my first 10 tasks are producer and that CorePoolSize is 10, then succeeding consumer tasks will go to queue and won't run until the queue is full? If so this behavior may cause deadlock because first 10 producers could go on wait, suspending all 10 threads of the Core.
When the queue is full?
I'm not sure I understood well the documentation, because Executors.newCachedThreadPool() seems to create a new Worker until maxPoolSize is reached and THEN it sends task to queue.
I'm a little confused.
Thank you
When you construct the ThreadPoolExecutor, you pass in an instance of BlockingQueue<Runnable> called workQueue, to hold the tasks, and it is this queue that is being referred to.
In fact, the section of the docs called "Queuing" goes into more detail about the phrase you're confused about:
Any BlockingQueue may be used to transfer and hold submitted tasks. The use of this queue interacts with pool sizing:
If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
As for your second part, about inter-task dependencies - in this case I don't think it's a good idea to put them into an ExecutorService at all. The ExecutorService is good for running a self-contained bit of code at some point in the future, but by design it's not meant to be strongly deterministic about when this happens, other than "at some convenient point in the (hopefully near) future, after tasks that were previously queued have started."
Combine this lack of precision of timing, with the hard ordering requirements that concurrent operation imposes, and you can see that having a producer and a consumer that need to talk to each other, put into a general purpose ExecutorService, is a recipe for very annoying and confusing bugs.
Yes, I'm sure you could get it to work with sufficient tweaking of parameters. However, it wouldn't be clear why it worked, it wouldn't be clear what the dependencies were, and when (not if) it broke, it would be very hard to diagnose. (Harder than normal concurrency problems, I suspect). The bottom line is that an ExecutorService isn't designed to run Runnables with hard timing restrictions, so this could even be broken by a new release of Java, because it doesn't have to work like this.
I think you're asking the wrong question, by looking at the details when perhaps your concepts are a little shaky. Perhaps if you explained what you wanted to achieve there would be a better way to go about it.
To clarify your first quote - if the executor already has corePoolSize threads running, and all of those threads are busy when a new task is submitted, it will not create any more threads, but will enqueue the task until one of the threads becomes free. It will only create a new thread (up to the maxPoolSize limit) when the queue becomes full. If the queue is huge (i.e. bounded only by memory constraints) then no more than corePoolSize threads will ever be created.
Executors.newCachedThreadPool() will create an executor with a zero-sized queue, so the queue is always full. This means that it will create a new thread (or re-use an idle one) as soon as you submit the task. As such, it's not a good demonstration of what the core/max/queue parameters are for.

Categories