views:

239

answers:

2

I'd like to have a ScheduledThreadPoolExecutor which also stops the last thread if there is no work to do, and creates (and keeps threads alive for some time) if there are new tasks. But once there is no more work to do, it should again discard all threads.

I naivly created it as new ScheduledThreadPoolExecutor(0) but as a consequence, no thread is ever created, nor any scheduled task is ever executed.

Can anybody tell me if I can achieve my goal without writing my own wrapper around the ScheduledThreadpoolExecutor?

Thanks in advance!

+1  A: 

I suspect that nothing provided in java.util.concurrent will do this for you, just because if you need a scheduled execution service, then you often have recurring tasks to perform. If you have a recurring task, then it usually makes more sense to just keep the same thread around and use it for the next recurrence of the task, rather than tearing down your thread and having to build a new one at the next recurrence.

Of course, a scheduled executor could be used for inserting delays between non-recurring tasks, or it could be used in cases where resources are so scarce and recurrence is so infrequent that it makes sense to tear down all your threads until new work arrives. So, I can see cases where your proposal would definitely make sense.

To implement this, I would consider trying to wrap a cached thread pool from Executors.newCachedThreadPool together with a single-threaded scheduled executor service (i.e. new ScheduledThreadPoolExecutor(1)). Tasks could be scheduled via the scheduled executor service, but the scheduled tasks would be wrapped in such a way that rather than having your single-threaded scheduled executor execute them, the single-threaded executor would hand them over to the cached thread pool for actual execution.

That compromise would give you a maximum of one thread running when there is absolutely no work to do, and it would give you as many threads as you need (within the limits of your system, of course) when there is lots of work to do.

Joe Carnahan
Thanks for the ellaborated answer. Actually, I am using the ScheduledThreadPool for delayed operations, not for repeated actions. And most of the actions are one-time actions and I'd hate to create a Thread every time and I'd also hate to explicitely share a ScheduledExecutorService manually between the various classes that need to do so.
Martin C.
+2  A: 

Actually you can do it, but its non-obvious:

  • Create a new ScheduledThreadPoolExecutor
  • In the constructor set the core threads to the maximum number of threads you want
  • set the keepAliveTime of the executor
  • and at last, allow the core threads to timeout

    m_Executor = new ScheduledThreadPoolExecutor ( 16,null );

    m_Executor.setKeepAliveTime ( 5, TimeUnit.SECONDS );
    m_Executor.allowCoreThreadTimeOut ( true );
    

    This works only with Java 6 though

Alex V.
Many thanks, that sounds quite exactly like what I need.
Martin C.