Questions about ThreadPoolExecutor

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

Questions about ThreadPoolExecutor

gyk
Hi,
 
    There are two things I need to achieve for my thread pool.
 
    1)  I need to have the pool customized such when I invokeAll on a Collection of Callables, I also get to specify how many threads I want to allocate to run this Collection of Callables.
 
    2) The run() method of the runnable (say A) that I submit to the pool might create other runnables (say a and b) which will in terms be submitted to the same pool.  It seems to me that my only choice would be to use the SynchronousQueue because if I were to use an ArrayBlockingQueue, it might cause a deadlock.  (Since the runnable a and b might not be run until A is finished and A can't finish until a and b are done.  Correct me if I am wrong.)   However, it looks like using SynchronusQueue requires the pool to be unbounded which I don't want.  I want a bounded pool.
 
Any suggestion on how I can achieve these two criteria using the 1.5 concurrency Executor. 
 
Thank you very much in advance for your valuable suggestions.
 
Grace
 

NOTICE: If received in error, please destroy and notify sender.  Sender does not waive confidentiality or privilege, and use is prohibited.


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

Re: Questions about ThreadPoolExecutor

Brian Goetz
>     1)  I need to have the pool customized such when I invokeAll on a
> Collection of Callables, I also get to specify how many threads I want
> to allocate to run this Collection of Callables.

You can create a custom Executor for each batch of Callables.  You will
probably want to use some other bounding mechanism to ensure that
aggregate number of threads created by such executors doesn't exceed
some threshold.

>     2) The run() method of the runnable (say A) that I submit to the
> pool might create other runnables (say a and b) which will in terms be
> submitted to the same pool.  

This is deadlock-prone unless the _pool_ is unbounded (or you can prove
that the number of tasks submitted will be less than the pool size.)

> However, it looks like
> using SynchronusQueue requires the pool to be unbounded which I don't
> want.  I want a bounded pool.

SynchronousQueue works best with unbounded pools; with bounded pools, it
will invoke the rejected execution handler to dispose of tasks submitted
in excess of the pool size.

Unless you can bound the task count somehow, you cannot have both of
what you want -- either bound the pool, or don't use tasks that depend
on other tasks.  Otherwise, you're playing Deadlock Roulette.

> Any suggestion on how I can achieve these two criteria using the 1.5
> concurrency Executor.

Tell us more about the _problem_ you are trying to solve, rather than
the solution you have in mind, and we could probably help further.


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

RE: Questions about ThreadPoolExecutor

gyk
In reply to this post by gyk
"You can create a custom Executor for each batch of Callables.  You will
probably want to use some other bounding mechanism to ensure that
aggregate number of threads created by such executors doesn't exceed
some threshold."

If I am to create an Executor for each batch of Callables, the threads
from Executor 1 could not be reused by threads from Executor 2, is that
correct?  Is this optimal?  Is this like a pool of Executors?


Basically, I am facing a customized thread pool class that is written
pre 1.5 and I want to replace that with the Executor.  The customized
thread pool class allows specifying the number of threads to run for
each batch because each batch is big and we don't want one thread
created per task of each batch.  If we create one thread per
task/Callable of each batch, one batch would take away all the thread
resources and won't allow other batches to start running.  Currently, if
thread count is exceeding a threshold, it would use the current thread
to run the tasks in the batch single-threadedly and use other threads in
pool when they become available. (But the "single-threadedly" would only
work for synchronous call and not asynchronous call).


I hope it makes sense.
Thank you very much.
Grace






-----Original Message-----
From: Brian Goetz [mailto:[hidden email]]
Sent: Wednesday, March 01, 2006 2:27 PM
To: Kwok, Grace (MSCIBARRA)
Cc: [hidden email]
Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor

>     1)  I need to have the pool customized such when I invokeAll on a
> Collection of Callables, I also get to specify how many threads I want

> to allocate to run this Collection of Callables.

You can create a custom Executor for each batch of Callables.  You will
probably want to use some other bounding mechanism to ensure that
aggregate number of threads created by such executors doesn't exceed
some threshold.


>     2) The run() method of the runnable (say A) that I submit to the
> pool might create other runnables (say a and b) which will in terms be

> submitted to the same pool.

This is deadlock-prone unless the _pool_ is unbounded (or you can prove
that the number of tasks submitted will be less than the pool size.)

> However, it looks like
> using SynchronusQueue requires the pool to be unbounded which I don't
> want.  I want a bounded pool.

SynchronousQueue works best with unbounded pools; with bounded pools, it
will invoke the rejected execution handler to dispose of tasks submitted
in excess of the pool size.

Unless you can bound the task count somehow, you cannot have both of
what you want -- either bound the pool, or don't use tasks that depend
on other tasks.  Otherwise, you're playing Deadlock Roulette.

> Any suggestion on how I can achieve these two criteria using the 1.5
> concurrency Executor.

Tell us more about the _problem_ you are trying to solve, rather than
the solution you have in mind, and we could probably help further.
--------------------------------------------------------

NOTICE: If received in error, please destroy and notify sender.  Sender does not waive confidentiality or privilege, and use is prohibited.

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

Re: Questions about ThreadPoolExecutor

Brian Goetz
> "You can create a custom Executor for each batch of Callables.  You will
> probably want to use some other bounding mechanism to ensure that
> aggregate number of threads created by such executors doesn't exceed
> some threshold."
>
> If I am to create an Executor for each batch of Callables, the threads
> from Executor 1 could not be reused by threads from Executor 2, is that
> correct?  Is this optimal?  Is this like a pool of Executors?

You are correct.  Optimal?  That depends on your requirements.

> Basically, I am facing a customized thread pool class that is written
> pre 1.5 and I want to replace that with the Executor.  The customized
> thread pool class allows specifying the number of threads to run for
> each batch because each batch is big and we don't want one thread
> created per task of each batch.  If we create one thread per
> task/Callable of each batch, one batch would take away all the thread
> resources and won't allow other batches to start running.  Currently, if
> thread count is exceeding a threshold, it would use the current thread
> to run the tasks in the batch single-threadedly and use other threads in
> pool when they become available. (But the "single-threadedly" would only
> work for synchronous call and not asynchronous call).

If each batch is big, then specifying a separate executor for each batch
is not going to be a big source of inefficiency.  You will still want to
allocate threads to executors in some sensible way, like using a
Semaphore.

Basic idea:
   N = total number of threads available for execution of all batches

   Semaphore sem = new Semaphore(s);

   Collection<Future> executeBatchCollection<Task> tasks, int nThreads) {
     sem.aquire(nThreads);
     try {
         ExecutorService exec = Executors.newFixedThreadpool(nThreads);
         Collection<Future> result = exec.invokeAll(tasks);
     }
     finally {
       exec.shutdownNow();
       sem.release(nThreads);
     }
   }



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

Re: Questions about ThreadPoolExecutor

Brian Goetz
>   N = total number of threads available for execution of all batches
>
>   Semaphore sem = new Semaphore(s);

This should be Semaphore(N);

>   Collection<Future> executeBatchCollection<Task> tasks, int nThreads) {
>     sem.aquire(nThreads);
>     try {
>         ExecutorService exec = Executors.newFixedThreadpool(nThreads);
>         Collection<Future> result = exec.invokeAll(tasks);

probably meant to return the result here

>     }
>     finally {
>       exec.shutdownNow();
>       sem.release(nThreads);
>     }
>   }

might want these in separate finally blocks, might want different
shutdown actions, but the approach is basically right -- to start a
batch, you have to get credit for the right number of threads from the
limited pool, and you return those credits when the batch is done.

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

Re: Questions about ThreadPoolExecutor

Joe Bowbeer
In reply to this post by gyk
On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
> "You can create a custom Executor for each batch of Callables.  You will
> probably want to use some other bounding mechanism to ensure that
> aggregate number of threads created by such executors doesn't exceed
> some threshold."
>

This could be done by having all of the dedicated executors submit
their work to one master executor.


> If I am to create an Executor for each batch of Callables, the threads
> from Executor 1 could not be reused by threads from Executor 2, is that
> correct?  Is this optimal?  Is this like a pool of Executors?
>

ThreadPoolExecutor per batch seems right to me.  If you want to
cleanup when a batch is done, you can call executorService.shutdown().

You can also call executorService.setKeepAliveTime() so that the idle
threads will self-terminate more or less automatically.

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

RE: Questions about ThreadPoolExecutor

gyk
In reply to this post by gyk
Thank you all for the valuable suggestions.

Do you mind explain this further?
"This could be done by having all of the dedicated executors submit
their work to one master executor."

 

Thanks, Grace


-----Original Message-----
From: Joe Bowbeer [mailto:[hidden email]]
Sent: Wednesday, March 01, 2006 5:17 PM
To: Kwok, Grace (MSCIBARRA)
Cc: Brian Goetz; [hidden email]
Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor

On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
> "You can create a custom Executor for each batch of Callables.  You
> will probably want to use some other bounding mechanism to ensure that

> aggregate number of threads created by such executors doesn't exceed
> some threshold."
>

This could be done by having all of the dedicated executors submit their
work to one master executor.


> If I am to create an Executor for each batch of Callables, the threads

> from Executor 1 could not be reused by threads from Executor 2, is
> that correct?  Is this optimal?  Is this like a pool of Executors?
>

ThreadPoolExecutor per batch seems right to me.  If you want to cleanup
when a batch is done, you can call executorService.shutdown().

You can also call executorService.setKeepAliveTime() so that the idle
threads will self-terminate more or less automatically.
--------------------------------------------------------

NOTICE: If received in error, please destroy and notify sender.  Sender does not waive confidentiality or privilege, and use is prohibited.

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

Re: Questions about ThreadPoolExecutor

Joe Bowbeer
On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
>
> Do you mind explain this further?
> "This could be done by having all of the dedicated executors submit
> their work to one master executor."
>
>

We call this beast a composite executor.  There's an example in the
Executor javadoc:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executor.html

The SerialExecutor example serializes the execution of a set of tasks
on another executor.

In your case, you'd write a BatchExecutor that submitted its tasks to
a master executor.  The master executor could be a cached ThreadPool
(Executors.newCachedThreadPool) with a maximumPoolSize to prevent
thread explosion.

Btw, another way to get a handle on thread creation across a set of
executors is to assign the same ThreadFactory to them all.  I wouldn't
make your factory too smart because then you'd be rewriting
ThreadPoolExecutor, but at least you'd be able to name the threads
logically and keep track of the total count, etc.


> -----Original Message-----
> From: Joe Bowbeer [mailto:[hidden email]]
> Sent: Wednesday, March 01, 2006 5:17 PM
> To: Kwok, Grace (MSCIBARRA)
> Cc: Brian Goetz; [hidden email]
> Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor
>
> On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
> > "You can create a custom Executor for each batch of Callables.  You
> > will probably want to use some other bounding mechanism to ensure that
>
> > aggregate number of threads created by such executors doesn't exceed
> > some threshold."
> >
>
> This could be done by having all of the dedicated executors submit their
> work to one master executor.
>
>
> > If I am to create an Executor for each batch of Callables, the threads
>
> > from Executor 1 could not be reused by threads from Executor 2, is
> > that correct?  Is this optimal?  Is this like a pool of Executors?
> >
>
> ThreadPoolExecutor per batch seems right to me.  If you want to cleanup
> when a batch is done, you can call executorService.shutdown().
>
> You can also call executorService.setKeepAliveTime() so that the idle
> threads will self-terminate more or less automatically.
> --------------------------------------------------------
>

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

RE: Questions about ThreadPoolExecutor

David Holmes-3
Joe writes:

> We call this beast a composite executor.  There's an example in the
> Executor javadoc:
>
> http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executor.html
>
> The SerialExecutor example serializes the execution of a set of tasks
> on another executor.
>
> In your case, you'd write a BatchExecutor that submitted its tasks to
> a master executor.  The master executor could be a cached ThreadPool
> (Executors.newCachedThreadPool) with a maximumPoolSize to prevent
> thread explosion.

I'm losing the plot here a bit. It seems there were two original
requirements:
 - bound the size of the pool
 - avoid task deadlocks

The suggestion for avoiding deadlock was to use a synchronous queue which
seemed to preclude using a bounded pool, hence an apparent conflict.

But to avoid deadlocks (more a gridlock: each executing task needs to submit
a new subtask but the pool is full so no one executes and we come to
stand-still) you always need sufficient threads for the maximum number of
concurrent tasks, or else revert to an "execute in the current thread"
rejection policy.

By batching things we seem to be reducing the pool size issue somewhat by
requiring that the pool contain as many threads as the maximum number of
concurrent tasks needed by any one batch. This is essence would serialize
batches. If the pool is greater than that number then we can allow some
overlap of batches and in the extreme we have enough threads for every
batch. Is that a reasonable summery?

BTW another option would be to change the task structure. Suppose that
originally we have:

    TaskA {
        // do some work
        spawn TaskB
        spawn TaskC
        join TaskA
        join TaskB
        // do more work
    }

Then instead you factor "do more work" into TaskD and have it submitted by
the last of TaskB and TaskC to complete. Of course this requires some
coordination between B and C, or some coordination infrastructure around
them.

Cheers,
David Holmes

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

Re: Questions about ThreadPoolExecutor

Joe Bowbeer
In reply to this post by Joe Bowbeer
One more hint:

[hidden email] wrote:
> Currently, if thread count is exceeding a threshold, it would use the
> current thread to run the tasks in the batch single-threadedly and use
> other threads in pool when they become available.

Note that this is similar to ThreadPoolExecutor.CallerRunsPolicy.

If you set the maximum pool size on your ThreadPoolExecutor and assign
CallerRunsPolicy() as the rejectedExecutionHandler, then tasks
submitted while the active thread limit has been reached will be
executed in the submitting thread.

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

Re: Questions about ThreadPoolExecutor

Gregg Wonderly-2
In reply to this post by David Holmes-3
It seems to me that two queues solve the problem.  Put A's in one queue, and a's
and b's into another which can be fixed sized.  Why isn't this the simplest and
most straight forward implementation?

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

RE: Questions about ThreadPoolExecutor

gyk
In reply to this post by gyk
>"If you set the maximum pool size on your ThreadPoolExecutor and assign
CallerRunsPolicy() as the rejectedExecutionHandler, then tasks
submitted while the active thread limit has been reached will be
executed in the submitting thread."

Thanks for the above hint.  This should fit part of my needs.  By using
this policy, it should avoid task deadlocks even if my pool is bounded,
correct?

>"In your case, you'd write a BatchExecutor that submitted its tasks to
a master executor. "

Since my original problem is to be

1) - able to specify the number of threads to run each batch of tasks.
(i.e. I have a batch of 100 tasks; I only want to allocate 6 threads to
be running them even if the pool has more than 6 threads available.  The
reasons are one, I don't want one batch to take away all the thread
resources and two, if the tasks are big stress to the db, I simply want
the control to be able to specify less threads to run them.)
2) - bound the size of the pool
3) - avoid task deadlocks
4) - would need something like invokeAll(..) in ExecutorService to wait
and get my result back.
5) - nice to be able to reuse threads in pool instead of creating an
Executor for each batch since some batch might be small, some are large.

In your suggestion of this BatchExecutor, in esssense, there is really
one Executor, I am not so clear on how I would achieve 1 and 4?  Would
my BatchExecutor has to be wise in figuring out the pace of dispatching
to the master executor so to satisfy X number of threads running the
batch of tasks?

Thank you very much for everyone's valuable time.
Grace


-----Original Message-----
From: Joe Bowbeer [mailto:[hidden email]]
Sent: Wednesday, March 01, 2006 7:14 PM
To: Kwok, Grace (MSCIBARRA)
Cc: [hidden email]
Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor

On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
>
> Do you mind explain this further?
> "This could be done by having all of the dedicated executors submit
> their work to one master executor."
>
>

We call this beast a composite executor.  There's an example in the
Executor javadoc:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executor.ht
ml

The SerialExecutor example serializes the execution of a set of tasks on
another executor.

In your case, you'd write a BatchExecutor that submitted its tasks to a
master executor.  The master executor could be a cached ThreadPool
(Executors.newCachedThreadPool) with a maximumPoolSize to prevent thread
explosion.

Btw, another way to get a handle on thread creation across a set of
executors is to assign the same ThreadFactory to them all.  I wouldn't
make your factory too smart because then you'd be rewriting
ThreadPoolExecutor, but at least you'd be able to name the threads
logically and keep track of the total count, etc.


> -----Original Message-----
> From: Joe Bowbeer [mailto:[hidden email]]
> Sent: Wednesday, March 01, 2006 5:17 PM
> To: Kwok, Grace (MSCIBARRA)
> Cc: Brian Goetz; [hidden email]
> Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor
>
> On 3/1/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:
> > "You can create a custom Executor for each batch of Callables.  You
> > will probably want to use some other bounding mechanism to ensure
> > that
>
> > aggregate number of threads created by such executors doesn't exceed

> > some threshold."
> >
>
> This could be done by having all of the dedicated executors submit
> their work to one master executor.
>
>
> > If I am to create an Executor for each batch of Callables, the
> > threads
>
> > from Executor 1 could not be reused by threads from Executor 2, is
> > that correct?  Is this optimal?  Is this like a pool of Executors?
> >
>
> ThreadPoolExecutor per batch seems right to me.  If you want to
> cleanup when a batch is done, you can call executorService.shutdown().
>
> You can also call executorService.setKeepAliveTime() so that the idle
> threads will self-terminate more or less automatically.
> --------------------------------------------------------
>
--------------------------------------------------------

NOTICE: If received in error, please destroy and notify sender.  Sender does not waive confidentiality or privilege, and use is prohibited.

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

Re: Questions about ThreadPoolExecutor

Joe Bowbeer
On 3/2/06, Kwok, Grace (MSCIBARRA) <[hidden email]> wrote:

> >"In your case, you'd write a BatchExecutor that submitted its tasks to
> a master executor. "
>
> Since my original problem is to be
>
> 1) - able to specify the number of threads to run each batch of tasks.
> (i.e. I have a batch of 100 tasks; I only want to allocate 6 threads to
> be running them even if the pool has more than 6 threads available.  The
> reasons are one, I don't want one batch to take away all the thread
> resources and two, if the tasks are big stress to the db, I simply want
> the control to be able to specify less threads to run them.)
> 2) - bound the size of the pool
> 3) - avoid task deadlocks
> 4) - would need something like invokeAll(..) in ExecutorService to wait
> and get my result back.
> 5) - nice to be able to reuse threads in pool instead of creating an
> Executor for each batch since some batch might be small, some are large.
>
> In your suggestion of this BatchExecutor, in esssense, there is really
> one Executor, I am not so clear on how I would achieve 1 and 4?  Would
> my BatchExecutor has to be wise in figuring out the pace of dispatching
> to the master executor so to satisfy X number of threads running the
> batch of tasks?
>

I wasn't trying to promote BatchExecutor, but to provide an example of
how one executor could proxy for a second.  The example I provided was
a SerialExecutor, that is, a batch of one.  Whereas in your case you'd
need an executor that dealt with larger batches.

If I understand your scenario correctly, the cleanest approach I can
think of would be to run each batch in a dedicated executor configured
as a cachedThreadPool with a maximumPoolSize appropriate for each
batch, a CallerRuns rejectedExecutionHandler, and a short
keepAliveTime.

The part of your scenario that I'm sure I don't understand is the
interdependency between tasks within and between batches.

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: Questions about ThreadPoolExecutor

Brian Goetz
In reply to this post by gyk
>> "If you set the maximum pool size on your ThreadPoolExecutor and assign
> CallerRunsPolicy() as the rejectedExecutionHandler, then tasks
> submitted while the active thread limit has been reached will be
> executed in the submitting thread."
>
> Thanks for the above hint.  This should fit part of my needs.  By using
> this policy, it should avoid task deadlocks even if my pool is bounded,
> correct?

Only with a zero-length task queue (i.e., SynchronousQueue.)  Otherwise,
the same deadlock risks apply.

>> "In your case, you'd write a BatchExecutor that submitted its tasks to
> a master executor. "
>
> Since my original problem is to be
>
> 1) - able to specify the number of threads to run each batch of tasks.
> (i.e. I have a batch of 100 tasks; I only want to allocate 6 threads to
> be running them even if the pool has more than 6 threads available.  The
> reasons are one, I don't want one batch to take away all the thread
> resources and two, if the tasks are big stress to the db, I simply want
> the control to be able to specify less threads to run them.)
> 2) - bound the size of the pool
> 3) - avoid task deadlocks
> 4) - would need something like invokeAll(..) in ExecutorService to wait
> and get my result back.
> 5) - nice to be able to reuse threads in pool instead of creating an
> Executor for each batch since some batch might be small, some are large.
>
> In your suggestion of this BatchExecutor, in esssense, there is really
> one Executor, I am not so clear on how I would achieve 1 and 4?  Would
> my BatchExecutor has to be wise in figuring out the pace of dispatching
> to the master executor so to satisfy X number of threads running the
> batch of tasks?

Here's another trick that might help.  It doesn't even required the
cascading executors -- if you're willing for your invokeAll to be
synchronous (which I think is OK by your requirements.)

You create a shared pool with 100 threads.  For each batch, you create a
semaphore with the number of threads that batch is allowed to use.  Each
permit represents the right to submit a task concurrently to the main
pool.  The permit is acquired before submitting the task, and released
by the task when its done.  I think this, along with the trick above of
combining caller-runs with SynchronousQueue meets all your requirements.

     public static ExecutorService exec
         = Executors.newFixedThreadPool(100);

     class Batch<T> {
         private final Collection<Callable<T>> tasks;
         private final Semaphore sem;

         public Batch(Collection<Callable<T>> tasks, int nThreads) {
             this.tasks = tasks;
             sem = new Semaphore(nThreads);
         }

         public Collection<Future<T>> invokeAll() throws
InterruptedException {
             List<Future<T>> results = new ArrayList<Future<T>>();
             for (final Callable<T> task : tasks) {
                 sem.acquire();
                 results.add(exec.submit(
                         new Callable<T>() {
                             public T call() throws Exception {
                                 try {
                                     return task.call();
                                 }
                                 finally {
                                     sem.release();
                                 }
                             }
                         }));
             }
             return results;
         }
     }

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

Re: Questions about ThreadPoolExecutor

Joe Bowbeer
On 3/2/06, Brian Goetz <[hidden email]> wrote:

> I think this, along with the trick above of combining caller-runs
> with SynchronousQueue meets all your requirements.
>
>      public static ExecutorService exec
>          = Executors.newFixedThreadPool(100);
>

Note that newFixedThreadPool uses an unbounded queue.

newCachedThreadPool would get you the synchronous queue, but I think
you'll need to invoke one of the ThreadPoolExecutor constructors
yourself regardless, because none of the Executors factory methods
provides everything you need, and you'll need a real
ThreadPoolExecutor in order to configure the queue, maximum pool size,
rejected execution handler, and keep-alive time.

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

Re: Questions about ThreadPoolExecutor

Brian Goetz
> newCachedThreadPool would get you the synchronous queue, but I think
> you'll need to invoke one of the ThreadPoolExecutor constructors
> yourself regardless, because none of the Executors factory methods
> provides everything you need, and you'll need a real
> ThreadPoolExecutor in order to configure the queue, maximum pool size,
> rejected execution handler, and keep-alive time.

This would work too, but doesn't give you a chance to bound the
aggregate thread count.

You could bound the aggregate thread count using a cached thread pool
and a second semaphore; one that requests nThread permits from the
master semaphore before starting an invokeAll, and returns them when
done.  That way, you could still say "Allow no more than N task
threads", and if too many batches are submitted, they block.

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

Re: Questions about ThreadPoolExecutor

Brian Goetz
In reply to this post by gyk
[ I think this message got eaten somehow ]

>> "If you set the maximum pool size on your ThreadPoolExecutor and assign
> CallerRunsPolicy() as the rejectedExecutionHandler, then tasks
> submitted while the active thread limit has been reached will be
> executed in the submitting thread."
>
> Thanks for the above hint.  This should fit part of my needs.  By using
> this policy, it should avoid task deadlocks even if my pool is bounded,
> correct?

Only with a zero-length task queue (i.e., SynchronousQueue.)  Otherwise,
the same deadlock risks apply.

>> "In your case, you'd write a BatchExecutor that submitted its tasks to
> a master executor. "
>
> Since my original problem is to be
>
> 1) - able to specify the number of threads to run each batch of tasks.
> (i.e. I have a batch of 100 tasks; I only want to allocate 6 threads to
> be running them even if the pool has more than 6 threads available.  The
> reasons are one, I don't want one batch to take away all the thread
> resources and two, if the tasks are big stress to the db, I simply want
> the control to be able to specify less threads to run them.)
> 2) - bound the size of the pool
> 3) - avoid task deadlocks
> 4) - would need something like invokeAll(..) in ExecutorService to wait
> and get my result back.
> 5) - nice to be able to reuse threads in pool instead of creating an
> Executor for each batch since some batch might be small, some are large.
>
> In your suggestion of this BatchExecutor, in esssense, there is really
> one Executor, I am not so clear on how I would achieve 1 and 4?  Would
> my BatchExecutor has to be wise in figuring out the pace of dispatching
> to the master executor so to satisfy X number of threads running the
> batch of tasks?

Here's another trick that might help.  It doesn't even required the
cascading executors -- if you're willing for your invokeAll to be
synchronous (which I think is OK by your requirements.)

You create a shared pool with 100 threads.  For each batch, you create a
semaphore with the number of threads that batch is allowed to use.  Each
permit represents the right to submit a task concurrently to the main
pool.  The permit is acquired before submitting the task, and released
by the task when its done.  I think this, along with the trick above of
combining caller-runs with SynchronousQueue meets all your requirements.

     public static ExecutorService exec
         = Executors.newFixedThreadPool(100);

     class Batch<T> {
         private final Collection<Callable<T>> tasks;
         private final Semaphore sem;

         public Batch(Collection<Callable<T>> tasks, int nThreads) {
             this.tasks = tasks;
             sem = new Semaphore(nThreads);
         }

         public Collection<Future<T>> invokeAll() throws
InterruptedException {
             List<Future<T>> results = new ArrayList<Future<T>>();
             for (final Callable<T> task : tasks) {
                 sem.acquire();
                 results.add(exec.submit(
                         new Callable<T>() {
                             public T call() throws Exception {
                                 try {
                                     return task.call();
                                 }
                                 finally {
                                     sem.release();
                                 }
                             }
                         }));
             }
             return results;
         }
     }


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

RE: Questions about ThreadPoolExecutor

gyk
In reply to this post by gyk
>"This would work too, but doesn't give you a chance to bound the
aggregate thread count.
>You could bound the aggregate thread count using a cached thread pool
and a second semaphore; one that requests nThread permits from the
master semaphore before starting an invokeAll, and returns them when
done.  That way, you could still say "Allow no more than N task
threads", and if too many batches are submitted, they block."


Wouldn't the above subject to our deadlock problem?  (Correct me if I am
wrong.)


So, perhaps I should call the ThreadPoolExecutor constructor,
ExecutorService exec = new ThreadPoolExecutor(10, 100, 10000000,
TimeUnit.NANOSECONDS
                                                                , new
SynchronousQueue(),
       
ThreadPoolExecutor.CallerRunsPolicy());

, put it with your Batch<T> class, and it should serve my needs.

Thank you all very much for your helpful suggestions!

Grace


 

-----Original Message-----
From: Brian Goetz [mailto:[hidden email]]
Sent: Thursday, March 02, 2006 1:33 PM
To: Joe Bowbeer
Cc: Kwok, Grace (MSCIBARRA); [hidden email]
Subject: Re: [concurrency-interest] Questions about ThreadPoolExecutor

> newCachedThreadPool would get you the synchronous queue, but I think
> you'll need to invoke one of the ThreadPoolExecutor constructors
> yourself regardless, because none of the Executors factory methods
> provides everything you need, and you'll need a real
> ThreadPoolExecutor in order to configure the queue, maximum pool size,

> rejected execution handler, and keep-alive time.

This would work too, but doesn't give you a chance to bound the
aggregate thread count.

You could bound the aggregate thread count using a cached thread pool
and a second semaphore; one that requests nThread permits from the
master semaphore before starting an invokeAll, and returns them when
done.  That way, you could still say "Allow no more than N task
threads", and if too many batches are submitted, they block.
--------------------------------------------------------

NOTICE: If received in error, please destroy and notify sender.  Sender does not waive confidentiality or privilege, and use is prohibited.

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