From javadoc for ThreadPoolExecutor:
When a new task is submitted in method execute(java.lang.Runnable)
.... If there are more than corePoolSize but less than
maximumPoolSize threads running, a new thread will be created only if
the queue is full.
How can I make ThreadPool that will start new thread instead of submitting task to queue in this situation?
Example:
I have thread with corePoolSize=5 and maxPoolSize=10 and unbounded queue.
Suppose corePoolSize threads is busy right now, and new task is arrived - pool must start new thread and execute new task.
Suppose maxPoolSize threads is busy right now, and new task is arrived - pool must persist task into queue, and first free thread must take this task and execute.
If you want a thread pool with a maximum size where the tasks are queued only when all the threads are busy.
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
The cached thread pool which will not queue tasks, but will create a new thread as required. It will re-use a thread if one is free.
ExecutorService service = Executors.newCachedThreadPool();
I've just posted this exact question and provided an answer there:
How to get the ThreadPoolExecutor to increase threads to max before queueing?
Sorry to not have found this question beforehand otherwise I would have just answered it.
To summarize the answer, I 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.
There is sample code in my answer. Again, sorry for the dup.
If you want to start new Thread each time regardless of availability of idle threads, then you need not ThreadPool at all - just create and start new Thread manually. This is better because your threads would die immediately after they do their work, and in the ThreadPool they would wait some time for new job but never get it, thus only wasting memory.
Related
In my code, I have a class containing a static final variable
private static final ForkJoinPool pool = new ForkJoinPool(availableCPUs - 1);
I have a long running task submitted to the pool, which would take all the CPU resource. Any other tasks submitted would be hanging.
However, when I switched to create a common pool
private static final ForkJoinPool pool = ForkJoinPool.commonPool();
All the tasks can be submitted and executed.
I was just wondering what the differences are between these two pieces of code. commonPool() still calls new ForkJoinPool() and passes the availableCPUs - 1
Also I noticed that commonPool() uses a factory of type SafeForkJoinWorkerThreadFactory while new ForkJoinPool() uses ForkJoinPool$DefaultForkJoinWorkerThreadFactory. Does this matter?
Thank you very much!
I think I figured it out.
ForkJoin maintains two types of queues: one general inbound queue and worker thread queues for each worker thread. All worker threads will fetch from the general inbound queue first and populate their worker threads. After one worker thread finishes all the tasks in its worker queue, it will try to steal from other worker threads. If there no other task to steal from other worker threads, the work thread will fetch from the general inbound queue again.
However, with common pool, the main thread will also help to process the tasks. The main thread does not have a worker queue though. Therefore, after finishing one task, the main thread will be able to fetch from general inbound queue.
Since by default, the ForkJoin queues are LIFO, the main thread will be able the fetch the last submitted tasks.
Documentation says:
The common pool is by default constructed with default parameters.
ForkJoinPool()
Creates a ForkJoinPool with parallelism equal to Runtime.availableProcessors(), using the default thread factory, no UncaughtExceptionHandler, and non-async LIFO processing mode.
So what makes you think that new ForkJoinPool(availableCPUs - 1) and ForkJoinPool.commonPool() would be pools of the same size?
If you only have 2 CPUs, then availableCPUs - 1 means you're creating a pool of 1 thread, i.e. it can only process one task at a time, so a long-running task will block all other tasks.
But with 2 CPUs, availableProcessors() means you're getting a common pool with 2 threads, i.e. it can process other tasks while a single long-running task is being processed.
The javadoc says:
When a new task is submitted [...], 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.
Does it mean that the count of simultaneously running thread in a fixed-size thread pool will be always less than corePoolSize unless the queue is full?
Does it mean that the count of simultaneously running thread in a fixed-size thread pool will be always less than corePoolSize unless the queue is full?
No, it does not.
Semantic approach
As I read it, and for fixed size pools, this quote states nothing about the number of active threads specifically with respect to the size of the queue. The only sentence tying the two is this one :
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
Which does not apply, since in a fixed-size pool has corePoolSize equal to maximumPoolSize. The "if" condition is never met.
What it does state though is :
When a new task is submitted [...], and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.
Threads will be created as long as the corePoolSize limit is not hit. As long as this limit is not hit, threads will not be reused (but they may die, on uncaught exception, or through the timeout feature of the pool). Which clearly leaves room for the creation of corePoolSize threads, if we create them fast enough or have a long enough queue.
Experimental approach
This knowledge allows us to imagine this scenario : make a fixed pool of size 2, with a waiting queue of size 5, and then submit two long running tasks to the pool. ("Long running" meaning the execution time of each task is one order of magnitude greater than the time it takes for the main thread to submit them, and for the thread pool to ackowledge their presence and work on them). A possible schedule for this is the following :
The main thread submits task T1 to the new, empty, pool
By virtue of the above quote, the corePoolSize not being hit yet, a new thread is created to execute T1.
The thread 1 starts executing T1
The main thread submits T2
As in step 2, a second thread is spawn, and the pool reaches corePoolSize
As in step 3, the second thread starts executing task T2
At this point, the thread pool has en empty queue, and a running thread count of exactly corePoolSize, and not "under corePoolSize", QED.
What it does mean :
Kind of the other way around, it means, the only way to get a number of thread greater than corePoolSize is having allconditions met at the same time :
a number of running threads greater than (or equal to) corePoolSize, and
maximumPoolSize greater than corePoolSize, and
a full queue
Is it possible to have a set of thread pools that share threads from a large thread pool instead of creating new thread?
In our RESTful API application, a request may involve several parallel tasks. To improve the performance, we want to execute parallel tasks in a thread pool which has a fixed number (say 200) of threads. But we also want to limit the max number of threads that each request can use. So I am thinking if it is possible to create a sub thread pool with a maximum pool size for each request, which does not create thread by itself but tries to fetch a new thread from the global thread pool and put job into queue if there is no available threads.
Has anyone done something similar? Or is there any other better solution?
Thanks!!
Instead of thread pools, think of executors. An executor consists of 2 things: a job queue and a thread pool. What you need is a light-weight executor for each request which has a job queue but has no threads. Instead, it passes jobs from its queue to the main executor (which owns all the threads). The trick is that the light-weight executor counts how many jobs it has submitted to the main executor, and stops passing jobs when the number exceeds the limit. Each job, before being passed to the main executor, is wrapped in an object of type Runnable which a) has the reference to the parent light-weight executor, b) executes the wrapped job and c) notifies the referenced executor when the job is finished so that the executor can pass another job to the main executor (or just decrease the job counter, if there is no jobs in the queue).
You could create a thread pool for every task e.g. Executors.newFixedThreadPool(10) This will do what you ask for with the inefficiency of potentially creating threads that a particular task instance doesn't need.
What do we mean by an idle thread? And when does it occur?
Context : ThreadPoolExecutor - it says even if there is an idle thread, if the corePoolSize is small, a new thread is created
In this context an idle thread is one that is owned/held by the ThreadPoolExecutor and is not currently running any Runnable/Callable.
When work is submitted to the TPE, and if an idle thread is chosen, then it becomes active and runs the Runnable/Callable. Once the Runnable/Callable completes the thread goes back to being idle (but may immediately become active again if there is more work to do and the TPE choses to use that now available thread).
it simply means when ThreadPool does not have any task to be executed or has more active threads than tasks available, then the excess thread go idle. It means they simply are not available to the scheduler (aka in sleep state).
Well in the context of the thread pool it means that it is created but it is not started; is waiting for jobs to start. What it means there there is that even if there are more threads than needed jobs new threads might be created, not to reach the case when a new job is needed to be submitted but there aren't threads available. Of course this goes up to a limit; also it depends on configuration.
What do we mean by an idle thread?
Idle thread : Worker threads are idle, if they are not running any tasks.
When does it occur?
When a thread has finish executing current task or not has any task to run, it becomes idle.
corePoolSize :
To keep atleast these many threads available for processing tasks. It reduces waiting time for the initial set of tasks, when the corePoolSize threads are idle or if corePoolSize limit has not been reached
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).
This question already has answers here:
What is the difference between corePoolSize and maxPoolSize in the Spring ThreadPoolTaskExecutor
(7 answers)
Closed 5 years ago.
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.
1) Why there is a need to create a new thread to handle the request if there are idle threads?
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
2) I don't understand the difference between corePoolSize and maximumPoolSize here. Secondly, how can a queue be full when threads are less than maximumPoolSize? Queue can only be full if threads are equal to or more than maximumPoolSize. Isn't it?
Here are Sun’s rules for thread creation in simple terms:
If the number of threads is less than the corePoolSize, create a new Thread to run a new task.
If the number of threads is equal (or greater than) the corePoolSize, put the task into the queue.
If the queue is full, and the number of threads is less than the maxPoolSize, create a new thread to run tasks in.
If the queue is full, and the number of threads is greater than or equal to maxPoolSize, reject the task.
Full article
You can find the definition of the terms corepoolsize and maxpoolsize in the javadoc. http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
The link above has the answer to your question. However, just to make it clear. The application will creating threads until it reaches the corePoolSize. It means that these number of threads should be sufficient to handle the inflow of tasks. After that the tasks will be queued. Once the queue is full the executor will start creating new threads. It is kind of balancing. What it essentially means is that the inflow of tasks is more than the processing capacity. So, Executor will start creating new threads again till it reaches Max number of threads. Again, a new threads will be created if and only if the queue is full.
Core and maximum pool sizes
A ThreadPoolExecutor will automatically adjust the pool size according to the bounds set by corePoolSize and maximumPoolSize .
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). link