views:

31

answers:

2

Is it possible to adjust the number of threads used by the Spring container's task support?

A: 

If you mean tasks, as in scheduled tasks, then I don't believe so, at least not directly, since task execution is normally synchronous - that is, two invocations of the same task are executed on the same thread - this is at least true for the JDK Timer class which uses a dedicated thread for each Timer - so multiple firings of the timer execute on the same thread.

If you want to have tasks executed against a thread pool, your best bet is to separate the task from the timer, and have the timer invoke your task on a thread pool. You get to configure the thread pool running the task and so you have full control over the number of threads.

The task invoked by the Timer looks like this

   public class TimerTaskInvoker extends TimerTask
   {
       TaskExecutor  executor;
       Runnable      taskToRun;

       public void run() {
          executor.execute(taskRoRun);
       }
   }

In your spring config

<!-- the thread pool for executing tasks -->
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  <property name="corePoolSize" value="5" />
  <property name="maxPoolSize" value="10" />
  <property name="queueCapacity" value="25" />
</bean>

<!-- invokes your actual task from the timer -->
<bean id="yourTaskInvoker" class="TimerTaskInvoker">
    <property name="executor" value="taskExecutor"/>
    <property name="taskToRun">
       <bean class="YourTaskClass">
          <!-- your task properties etc... -->
       </bean>
    </property>
</bean>

<!-- schedules execution of yourTaskInvoker -->    
<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
    <!-- wait 10 seconds before starting repeated execution -->
    <property name="delay" value="10000" />
    <!-- run every 50 seconds -->
    <property name="period" value="50000" />
    <property name="timerTask" ref="yourTaskInvoker" />
</bean>
mdma
+1  A: 

If you want to adjust it at runtime, then I believe your only choice is to do it programatically.

Inject a java.util.concurrent.ExecutorServiceinto Spring's task support like this:

<bean id="executorService" class="java.util.concurrent.Executors"
    factory-method="newFixedThreadPool">
    <constructor-arg value="5" />
</bean>

<task:annotation-driven executor="executorService" />

Then you can adjust the threads used by the ExecutorService like this:

@Inject
ExecutorService executorService;

public void adjustPoolSize() {
    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService;
    threadPoolExecutor.setMaximumPoolSize(10);
    threadPoolExecutor.setCorePoolSize(20);
}

I have written more about concurrency with Spring here.

Espen