Thread Pools

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Thread Pools

superuser

Hi, I know this has come up again and again, (I think I brought it up once or twice ;-) But are there any plans to add a “preferExistingThreads()” to the ThreadPoolExecutor, to address the issue of dynamic pool sizing, or is there any way I can extend these classes to do such?

 

IE I would like a:

1) potentially infinite queue of tasks (currently using a LinkedBlockingQueue)

2) executed by up to MAX threads concurrently

3) which go away after a period of inactivity, allowing the pool to shrink to MIN (or zero) size

4) preferring to use already existing threads rather than creating new ones

 

This is currently impossible with the current setup AFAICS; I have continued to have to use my own thread pools because of this, though I would love to switch to the standard JUC classes. #3 was covered in JDK 6 with the capability to allow core threads to timeout, but I cannot find a way to make #4 possible with current JUC. The existing behaviour will always end up creating CORE threads even though they are unnecessary to execute existing work.

 

Thanks in advance for any replies.

 

 

Best Regards,

 

Patrick


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Thread Pools

Joe Bowbeer
On 7/21/06, Patrick Eger <[hidden email]> wrote:

>
> Hi, I know this has come up again and again, (I think I brought it up once
> or twice ;-) But are there any plans to add a "preferExistingThreads()" to
> the ThreadPoolExecutor, to address the issue of dynamic pool sizing, or is
> there any way I can extend these classes to do such?
>
> IE I would like a:
>
> 1) potentially infinite queue of tasks (currently using a
> LinkedBlockingQueue)
>
> 2) executed by up to MAX threads concurrently
>
> 3) which go away after a period of inactivity, allowing the pool to shrink
> to MIN (or zero) size
>
> 4) preferring to use already existing threads rather than creating new ones
>
> This is currently impossible with the current setup AFAICS; I have continued
> to have to use my own thread pools because of this, though I would love to
> switch to the standard JUC classes. #3 was covered in JDK 6 with the
> capability to allow core threads to timeout, but I cannot find a way to make
> #4 possible with current JUC. The existing behaviour will always end up
> creating CORE threads even though they are unnecessary to execute existing
> work.
>
> Thanks in advance for any replies.
>

To recap, the problem you're trying to overcome is that TPE prefers
(1) to create a core thread, (2) queue task, (3) create additional
thread.

In other words, MAX_THREADS is effectively ignored if queue is unbounded:

    ExecutorService newEgerThreadPool() {
        return new ThreadPoolExecutor(0, MAX_THREADS,
                                      60L, TimeUnit.SECONDS,
                                      new LinkedQueue<Runnable>());
    }

So you're requesting an option to switch priority of 2 and 3.

I can't address that but I do see a new allowCoreThreadTimeOut method
in the pipeline that might have the same effect:

http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/
  => java/util/concurrent/ThreadPoolExecutor.java

pool.allowCoreThreadTimeOut(true) can be used to apply the time-out
policy to core threads as well, so long as the keepAliveTime value is
non-zero.

I think this might work:

    ExecutorService newEgerThreadPool() {
        ThreadPoolExecutor pool =
            new ThreadPoolExecutor(MAX_THREADS, MAX_THREADS,
                                      60L, TimeUnit.SECONDS,
                                      new LinkedQueue<Runnable>());
        pool.allowCoreThreadTimeOut(true);
        return pool;
    }

--Joe
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Thread Pools

superuser
In reply to this post by superuser
Thanks, I've tried this but it will create all MAX_THREADS before
reusing any of them, IE will still prefer creating a new thread before
reusing an existing (idle) one. I believe the old concurrent.jar has a
set of parameters that could produce this behaviour, but the newer, more
modular JUC design does not...

Best Regards,

Patrick


-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Joe
Bowbeer
Sent: Friday, July 21, 2006 12:54 PM
To: concurrency-interest
Subject: Re: [concurrency-interest] Thread Pools

On 7/21/06, Patrick Eger <[hidden email]> wrote:
>
> Hi, I know this has come up again and again, (I think I brought it up
once
> or twice ;-) But are there any plans to add a
"preferExistingThreads()" to
> the ThreadPoolExecutor, to address the issue of dynamic pool sizing,
or is

> there any way I can extend these classes to do such?
>
> IE I would like a:
>
> 1) potentially infinite queue of tasks (currently using a
> LinkedBlockingQueue)
>
> 2) executed by up to MAX threads concurrently
>
> 3) which go away after a period of inactivity, allowing the pool to
shrink
> to MIN (or zero) size
>
> 4) preferring to use already existing threads rather than creating new
ones
>
> This is currently impossible with the current setup AFAICS; I have
continued
> to have to use my own thread pools because of this, though I would
love to
> switch to the standard JUC classes. #3 was covered in JDK 6 with the
> capability to allow core threads to timeout, but I cannot find a way
to make
> #4 possible with current JUC. The existing behaviour will always end
up
> creating CORE threads even though they are unnecessary to execute
existing
> work.
>
> Thanks in advance for any replies.
>

To recap, the problem you're trying to overcome is that TPE prefers
(1) to create a core thread, (2) queue task, (3) create additional
thread.

In other words, MAX_THREADS is effectively ignored if queue is
unbounded:

    ExecutorService newEgerThreadPool() {
        return new ThreadPoolExecutor(0, MAX_THREADS,
                                      60L, TimeUnit.SECONDS,
                                      new LinkedQueue<Runnable>());
    }

So you're requesting an option to switch priority of 2 and 3.

I can't address that but I do see a new allowCoreThreadTimeOut method
in the pipeline that might have the same effect:

http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/
  => java/util/concurrent/ThreadPoolExecutor.java

pool.allowCoreThreadTimeOut(true) can be used to apply the time-out
policy to core threads as well, so long as the keepAliveTime value is
non-zero.

I think this might work:

    ExecutorService newEgerThreadPool() {
        ThreadPoolExecutor pool =
            new ThreadPoolExecutor(MAX_THREADS, MAX_THREADS,
                                      60L, TimeUnit.SECONDS,
                                      new LinkedQueue<Runnable>());
        pool.allowCoreThreadTimeOut(true);
        return pool;
    }

--Joe
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Thread Pools

Doug Lea
In reply to this post by superuser
Patrick Eger wrote:

>
> IE I would like a:
>
> 1) potentially infinite queue of tasks (currently using a
> LinkedBlockingQueue)
>
> 2) executed by up to MAX threads concurrently
>
> 3) which go away after a period of inactivity, allowing the pool to
> shrink to MIN (or zero) size
>
> 4) preferring to use already existing threads rather than creating new ones
>


All but (4) are straightforward.

By (4) I assume you mean to use an existing thread only if
it is "idle". This is just about impossible to deterministically
guarantee, at least when using an unbounded queue.
The pool cannot know for sure whether an existing thread is idle.
It only knows whether there are fewer or more than target number
of threads, and whether the queue is full, which it never is for
unbounded ones. Problematic cases include those where an
idle-looking thread is in the process of dequeuing a task and
so will momentarily run it. You might be content with an
implementation that ignores such cases and approximates (4)
by for example, counting threads blocked on workQueue.take.
But it would probably be a bad idea for us to add such capabilities --
they invite a  stream of bug reports when "approximately" doesn't
cover particular use cases well. (For example, here, it is hard
to avoid the pathology of a large number of threads trying
to submit tasks at the same time, and all of them thinking that
they don't need to create a new thread because there is an idle one.)

ThreadPoolExecutor tries to cover as wide a set of use cases as
can all be handled by the same overall design. It does cover most
common uses. But even at that, we have had to revamp parts of the
implementation now and then to get rid of unwanted unforeseen
interactions among various parameters and methods.

So, if you really need this behavior, it looks like you will
need a custom implementation. Or you might decide that plain
newFixedThreadPools are OK for your application after all?

-Doug
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Thread Pools

Joe Bowbeer
In reply to this post by superuser
On 7/21/06, Patrick Eger <[hidden email]> wrote:
> Thanks, I've tried this but it will create all MAX_THREADS before
> reusing any of them, IE will still prefer creating a new thread before
> reusing an existing (idle) one.

Does lowering the linger time to almost nothing approximate the right behavior?

>From the description you sent today, I'm guessing that thread start-up
time is not a big performance factor.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Thread Pools

superuser
In reply to this post by superuser
A lower linger time does help out indeed with the thread count, however
in my case it almost degenerates into no thread pool at all (IE short
timeout + not re-using existing threads = lots of thread create/delete).

I can't say thread startup is *too* big of a deal, but it is noticeable
in our CPU timing (moreso on windows with it's not-so-hot threading).


-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Joe
Bowbeer
Sent: Monday, July 24, 2006 11:23 AM
To: concurrency-interest
Subject: Re: [concurrency-interest] Thread Pools

On 7/21/06, Patrick Eger <[hidden email]> wrote:
> Thanks, I've tried this but it will create all MAX_THREADS before
> reusing any of them, IE will still prefer creating a new thread before
> reusing an existing (idle) one.

Does lowering the linger time to almost nothing approximate the right
behavior?

>From the description you sent today, I'm guessing that thread start-up
time is not a big performance factor.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest