Patrick Wright wrote:
On Fri, Jun 4, 2010 at 10:11 PM, Gregg Wonderly <[email protected]> wrote:
I'd have to say no for the existing Executor implementations in the JDK.
The concurrency utilities related to Executor in the JDK are tailored for,
and specifically limited to applications where you have unrelated tasks that
need to be throttled amongst a limited set of threads.
River's TaskManager will always create more threads, but will prune those
threads after they sit idle for too long. We need this behavior to keep
away from distributed deadlock which can occur anytime another remote
operation might be the only way that progress can happen in the overall
processing of a distributed application.
Be very careful where you use j.u.c ThreadPoolExecutor et.al, because of
their design. It would be possible to use an appropriate Executor
implementation, but it would have to behave like TaskManager and always
create a new thread for new work, when no idle threads are available.
Hi Gregg
This is not how I understood ThreadPoolExecutor, even from the JavaDoc
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html
"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."
and
"f the pool currently has more than corePoolSize threads, excess
threads will be terminated if they have been idle for more than the
keepAliveTime (see getKeepAliveTime(java.util.concurrent.TimeUnit)).
This provides a means of reducing resource consumption when the pool
is not being actively used. If the pool becomes more active later, new
threads will be constructed."
Under what configuration of TPE would we see a problem?
Anytime that you need more than corePoolSize threads, you risk seeing a task not
being executed immediately. The fact that there is a maximumPoolSize is the
bigger issue though. Only that many total threads can ever be running. If you
know enough about all parts of all services and clients using your River
application, you might be able to accurately guess what maximumPoolSize would
need to be. But ultimately, in a distributed application where circular
invocation scenarios are possible, you need a lot of information and there has
to be a lot of control in the applications to make sure that there are never
more than maximumPoolSize simultaneous method invocations in an instance.
I don't think that is possible, nor really a good idea to have a
maximumPoolSize. A thread pool design, like TaskManager, where only a minimum
exists, is the type of design we need in River.
Even today, I am working on debugging an old application where
ThreadPoolExecutor was used and the maximumPoolSize is creating extended delays
in processing until some timeouts occur and fallback to a single threaded
approach to try and recover. So, this is an important issue with how TPE was
designed to work.
Gregg Wonderly