diff --git a/spring-framework-reference/src/scheduling.xml b/spring-framework-reference/src/scheduling.xml
index fe24813ce3..024bf5a413 100644
--- a/spring-framework-reference/src/scheduling.xml
+++ b/spring-framework-reference/src/scheduling.xml
@@ -1,217 +1,183 @@
-
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
- Task Execution and Scheduling
-
- Introduction
-
- The Spring Framework provides abstractions for asynchronous execution and scheduling of tasks
- with the TaskExecutor and TaskScheduler
- interfaces, respectively. Spring also features implementations of those interfaces that support
- thread pools or delegation to CommonJ within an application server environment. Ultimately
- the use of these implementations behind the common interfaces abstracts away the differences
- between Java SE 5, Java SE 6 and Java EE environments.
-
-
- Spring also features integration classes for supporting scheduling with the
- Timer, part of the JDK since 1.3, and the Quartz Scheduler
- (). Both of those schedulers
- are set up using a FactoryBean with optional references
- to Timer or Trigger instances, respectively.
- Furthermore, a convenience class for both the Quartz Scheduler and the Timer is
- available that allows you to invoke a method of an existing target object
- (analogous to the normal MethodInvokingFactoryBean operation).
-
-
+ Task Execution and Scheduling
-
- The Spring TaskExecutor abstraction
+
+ Introduction
- Spring 2.0 introduces a new abstraction for dealing with
- executors. Executors are the Java 5 name for the concept of
- thread pools. The "executor" naming is due to the fact that there
- is no guarantee that the underlying implementation is actually a
- pool; an executor may be single-threaded or even synchronous.
- Spring's abstraction hides implementation details between
- Java SE 1.4, Java SE 5 and Java EE environments.
+ The Spring Framework provides abstractions for asynchronous
+ execution and scheduling of tasks with the
+ TaskExecutor and
+ TaskScheduler interfaces, respectively.
+ Spring also features implementations of those interfaces that support
+ thread pools or delegation to CommonJ within an application server
+ environment. Ultimately the use of these implementations behind the common
+ interfaces abstracts away the differences between Java SE 5, Java SE 6 and
+ Java EE environments.
- Spring's TaskExecutor interface is
- identical to the java.util.concurrent.Executor
- interface. In fact, its primary reason for existence is to abstract away
- the need for Java 5 when using thread pools. The interface has a single
- method execute(Runnable task) that accepts a task
- for execution based on the semantics and configuration of the thread pool.
- The TaskExecutor was originally
- created to give other Spring components an abstraction for thread pooling where
- needed. Components such as the ApplicationEventMulticaster,
- JMS's AbstractMessageListenerContainer,
- and Quartz integration all use the TaskExecutor
- abstraction to pool threads. However, if your beans need thread pooling behavior,
- it is possible to use this abstraction for your own needs.
-
-
- TaskExecutor types
- There are a number of pre-built implementations of
- TaskExecutor included with the
- Spring distribution. In all likelihood, you shouldn't ever
- need to implement your own.
-
-
-
-
- SimpleAsyncTaskExecutor
-
+ Spring also features integration classes for supporting scheduling
+ with the Timer, part of the JDK since 1.3, and the
+ Quartz Scheduler (). Both of those
+ schedulers are set up using a FactoryBean
+ with optional references to Timer or
+ Trigger instances, respectively. Furthermore, a
+ convenience class for both the Quartz Scheduler and the
+ Timer is available that allows you to invoke a
+ method of an existing target object (analogous to the normal
+ MethodInvokingFactoryBean operation).
+
-
- This implementation does not reuse any threads,
- rather it starts up a new thread for each
- invocation. However, it does support a
- concurrency limit which will block any
- invocations that are over the limit until a slot
- has been freed up. If you're looking for true
- pooling, keep scrolling further down the page.
-
-
-
-
-
- SyncTaskExecutor
-
+
+ The Spring TaskExecutor
+ abstraction
-
- This implementation doesn't execute
- invocations asynchronously. Instead, each
- invocation takes place in the calling thread. It
- is primarily used in situations where
- multithreading isn't necessary such as simple
- test cases.
-
-
-
-
-
- ConcurrentTaskExecutor
-
+ Spring 2.0 introduces a new abstraction for dealing with executors.
+ Executors are the Java 5 name for the concept of thread pools. The
+ "executor" naming is due to the fact that there is no guarantee that the
+ underlying implementation is actually a pool; an executor may be
+ single-threaded or even synchronous. Spring's abstraction hides
+ implementation details between Java SE 1.4, Java SE 5 and Java EE
+ environments.
-
- This implementation is a wrapper for a Java 5
- java.util.concurrent.Executor.
- There is an alternative,
- ThreadPoolTaskExecutor,
- that exposes the Executor
- configuration parameters as bean properties. It
- is rare to need to use the ConcurrentTaskExecutor
- but if the
- ThreadPoolTaskExecutor
- isn't robust enough for your needs, the
- ConcurrentTaskExecutor
- is an alternative.
-
-
-
-
-
- SimpleThreadPoolTaskExecutor
-
-
-
- This implementation is actually a subclass of
- Quartz's SimpleThreadPool
- which listens to Spring's lifecycle callbacks.
- This is typically used when you have a
- thread pool that may need to be shared by both
- Quartz and non-Quartz components.
-
-
+ Spring's TaskExecutor interface is
+ identical to the java.util.concurrent.Executor
+ interface. In fact, its primary reason for existence is to abstract away
+ the need for Java 5 when using thread pools. The interface has a single
+ method execute(Runnable task) that accepts a task
+ for execution based on the semantics and configuration of the thread
+ pool.
-
-
- ThreadPoolTaskExecutor
-
-
-
-
- It is not possible to use any backport or
- alternate versions of the
- java.util.concurrent
- package with this implementation. Both Doug
- Lea's and Dawid Kurzyniec's implementations
- use different package structures which will
- prevent them from working correctly.
-
-
+ The TaskExecutor was originally
+ created to give other Spring components an abstraction for thread pooling
+ where needed. Components such as the
+ ApplicationEventMulticaster, JMS's
+ AbstractMessageListenerContainer, and Quartz
+ integration all use the TaskExecutor
+ abstraction to pool threads. However, if your beans need thread pooling
+ behavior, it is possible to use this abstraction for your own
+ needs.
-
- This implementation can only be used in a Java 5
- environment but is also the most commonly used
- one in that environment. It exposes bean properties for
- configuring a
- java.util.concurrent.ThreadPoolExecutor
- and wraps it in a TaskExecutor.
- If you need something advanced such as a
- ScheduledThreadPoolExecutor,
- it is recommended that you use a
- ConcurrentTaskExecutor
- instead.
-
-
-
-
-
- TimerTaskExecutor
-
+
+ TaskExecutor types
-
- This implementation uses a single
- TimerTask
- as its backing implementation. It's different
- from the
- SyncTaskExecutor
- in that the method invocations are executed in a
- separate thread, although they are synchronous
- in that thread.
-
-
-
-
-
- WorkManagerTaskExecutor
-
-
-
- CommonJ is a set of specifications jointly
- developed between BEA and IBM. These
- specifications are not Java EE standards, but
- are standard across BEA's and IBM's
- Application Server implementations.
-
+ There are a number of pre-built implementations of
+ TaskExecutor included with the Spring
+ distribution. In all likelihood, you shouldn't ever need to implement
+ your own.
-
- This implementation uses the CommonJ WorkManager
- as its backing implementation and is the central
- convenience class for setting up a CommonJ
- WorkManager reference in a Spring context.
- Similar to the
- SimpleThreadPoolTaskExecutor,
- this class implements the WorkManager
- interface and therefore can be used directly as
- a WorkManager as well.
-
-
+
+
+ SimpleAsyncTaskExecutor
-
-
+ This implementation does not reuse any threads, rather it
+ starts up a new thread for each invocation. However, it does support
+ a concurrency limit which will block any invocations that are over
+ the limit until a slot has been freed up. If you're looking for true
+ pooling, keep scrolling further down the page.
+
-
- Using a TaskExecutor
- Spring's TaskExecutor implementations
- are used as simple JavaBeans. In the example below, we define
- a bean that uses the ThreadPoolTaskExecutor
- to asynchronously print out a set of messages.
+
+ SyncTaskExecutor
- This implementation doesn't execute invocations
+ asynchronously. Instead, each invocation takes place in the calling
+ thread. It is primarily used in situations where multithreading
+ isn't necessary such as simple test cases.
+
+
+
+ ConcurrentTaskExecutor
+
+ This implementation is a wrapper for a Java 5
+ java.util.concurrent.Executor. There is an
+ alternative, ThreadPoolTaskExecutor, that
+ exposes the Executor configuration parameters
+ as bean properties. It is rare to need to use the
+ ConcurrentTaskExecutor but if the ThreadPoolTaskExecutor
+ isn't robust enough for your needs, the
+ ConcurrentTaskExecutor is an
+ alternative.
+
+
+
+ SimpleThreadPoolTaskExecutor
+
+ This implementation is actually a subclass of Quartz's
+ SimpleThreadPool which listens to Spring's
+ lifecycle callbacks. This is typically used when you have a thread
+ pool that may need to be shared by both Quartz and non-Quartz
+ components.
+
+
+
+ ThreadPoolTaskExecutor
+
+
+ It is not possible to use any backport or alternate versions
+ of the java.util.concurrent package with
+ this implementation. Both Doug Lea's and Dawid Kurzyniec's
+ implementations use different package structures which will
+ prevent them from working correctly.
+
+
+ This implementation can only be used in a Java 5 environment
+ but is also the most commonly used one in that environment. It
+ exposes bean properties for configuring a
+ java.util.concurrent.ThreadPoolExecutor and
+ wraps it in a TaskExecutor. If you
+ need something advanced such as a
+ ScheduledThreadPoolExecutor, it is
+ recommended that you use a ConcurrentTaskExecutor
+ instead.
+
+
+
+ TimerTaskExecutor
+
+ This implementation uses a single
+ TimerTask as its backing implementation. It's
+ different from the SyncTaskExecutor
+ in that the method invocations are executed in a separate thread,
+ although they are synchronous in that thread.
+
+
+
+ WorkManagerTaskExecutor
+
+
+ CommonJ is a set of specifications jointly developed between
+ BEA and IBM. These specifications are not Java EE standards, but
+ are standard across BEA's and IBM's Application Server
+ implementations.
+
+
+ This implementation uses the CommonJ WorkManager as its
+ backing implementation and is the central convenience class for
+ setting up a CommonJ WorkManager reference in a Spring context.
+ Similar to the SimpleThreadPoolTaskExecutor,
+ this class implements the WorkManager interface and therefore can be
+ used directly as a WorkManager as well.
+
+
+
+
+
+ Using a TaskExecutor
+
+ Spring's TaskExecutor
+ implementations are used as simple JavaBeans. In the example below, we
+ define a bean that uses the
+ ThreadPoolTaskExecutor to asynchronously print
+ out a set of messages.
+
+ import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
@@ -236,41 +202,43 @@ public class TaskExecutorExample {
}
public void printMessages() {
- for(int i = 0; i < 25; i++) {
+ for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
-}]]>
-
- As you can see, rather than retrieving a thread from the
- pool and executing yourself, you add your Runnable
- to the queue and the TaskExecutor
- uses its internal rules to decide when the task gets executed.
-
- To configure the rules that the TaskExecutor
- will use, simple bean properties have been exposed.
-
-
-
-
-
-
+}
-
-
-]]>
+ As you can see, rather than retrieving a thread from the pool and
+ executing yourself, you add your Runnable to the
+ queue and the TaskExecutor uses its
+ internal rules to decide when the task gets executed.
-
-
+ To configure the rules that the
+ TaskExecutor will use, simple bean
+ properties have been exposed.
-
- The Spring TaskScheduler abstraction
+ <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>
- In addition to the TaskExecutor
- abstraction, Spring 3.0 introduces a TaskScheduler
- with a variety of methods for scheduling tasks to run at some point in the future.
-
-
+
+
+
+
+ The Spring TaskScheduler
+ abstraction
+
+ In addition to the TaskExecutor
+ abstraction, Spring 3.0 introduces a
+ TaskScheduler with a variety of methods for
+ scheduling tasks to run at some point in the future.
+
+ public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
@@ -284,42 +252,44 @@ public class TaskExecutorExample {
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
-}]]>
+}
- The simplest method is the one named 'schedule' that takes a
- Runnable and Date
- only. That will cause the task to run once after the specified time. All of
- the other methods are capable of scheduling tasks to run repeatedly. The
- fixed-rate and fixed-delay methods are for simple, periodic execution, but
- the method that accepts a Trigger is much more flexible.
+ The simplest method is the one named 'schedule' that takes a
+ Runnable and Date
+ only. That will cause the task to run once after the specified time. All
+ of the other methods are capable of scheduling tasks to run repeatedly.
+ The fixed-rate and fixed-delay methods are for simple, periodic execution,
+ but the method that accepts a Trigger is much more flexible.
-
- The Trigger interface
+
+ The Trigger interface
- The Trigger interface is
- essentially inspired by JSR-236, which, as of Spring 3.0, has not yet
- been officially implemented. The basic idea of the
- Trigger is that execution times may be
- determined based on past execution outcomes or even arbitrary
- conditions. If these determinations do take into account the outcome of
- the preceding execution, that information is available within a
- TriggerContext. The
- Trigger interface itself is quite
- simple:
- The Trigger interface is
+ essentially inspired by JSR-236, which, as of Spring 3.0, has not yet
+ been officially implemented. The basic idea of the
+ Trigger is that execution times may be
+ determined based on past execution outcomes or even arbitrary
+ conditions. If these determinations do take into account the outcome of
+ the preceding execution, that information is available within a
+ TriggerContext. The
+ Trigger interface itself is quite
+ simple:
+
+ public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
-}]]>
+}
- As you can see, the TriggerContext
- is the most important part. It encapsulates all of the relevant data,
- and is open for extension in the future if necessary. The
- TriggerContext is an interface (a
- SimpleTriggerContext implementation is used by
- default). Here you can see what methods are available for
- Trigger implementations.
- As you can see, the TriggerContext
+ is the most important part. It encapsulates all of the relevant data,
+ and is open for extension in the future if necessary. The
+ TriggerContext is an interface (a
+ SimpleTriggerContext implementation is used by
+ default). Here you can see what methods are available for
+ Trigger implementations.
+
+ public interface TriggerContext {
Date lastScheduledExecutionTime();
@@ -327,336 +297,356 @@ public class TaskExecutorExample {
Date lastCompletionTime();
-}]]>
-
+}
+
-
- Trigger implementations
+
+ Trigger implementations
- Spring provides two implementations of the
- Trigger interface. The most interesting
- one is the CronTrigger. It enables the
- scheduling of tasks based on cron expressions. For example the
- following task is being scheduled to run 15 minutes past each hour but
- only during the 9-to-5 "business hours" on weekdays.
-
+ Spring provides two implementations of the
+ Trigger interface. The most interesting
+ one is the CronTrigger. It enables the scheduling
+ of tasks based on cron expressions. For example the following task is
+ being scheduled to run 15 minutes past each hour but only during the
+ 9-to-5 "business hours" on weekdays.
- The other out-of-the-box implementation is a
- PeriodicTrigger that accepts a fixed period, an
- optional initial delay value, and a boolean to indicate whether the
- period should be interpreted as a fixed-rate or a fixed-delay. Since
- the TaskScheduler interface already
- defines methods for scheduling tasks at a fixed-rate or with a
- fixed-delay, those methods should be used directly whenever possible.
- The value of the PeriodicTrigger implementation
- is that it can be used within components that rely on the
- Trigger abstraction. For example, it may
- be convenient to allow periodic triggers, cron-based triggers, and even
- custom trigger implementations to be used interchangeably. Such a
- component could take advantage of dependency injection so that such
- Triggers could be configured externally.
-
-
+ scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI"));
-
- TaskScheduler implementations
+ The other out-of-the-box implementation is a
+ PeriodicTrigger that accepts a fixed period, an
+ optional initial delay value, and a boolean to indicate whether the
+ period should be interpreted as a fixed-rate or a fixed-delay. Since the
+ TaskScheduler interface already defines
+ methods for scheduling tasks at a fixed-rate or with a fixed-delay,
+ those methods should be used directly whenever possible. The value of
+ the PeriodicTrigger implementation is that it can
+ be used within components that rely on the
+ Trigger abstraction. For example, it may
+ be convenient to allow periodic triggers, cron-based triggers, and even
+ custom trigger implementations to be used interchangeably. Such a
+ component could take advantage of dependency injection so that such
+ Triggers could be configured
+ externally.
+
- As with Spring's TaskExecutor
- abstraction, the primary benefit of the
- TaskScheduler is that code relying on
- scheduling behavior need not be coupled to a particular scheduler
- implementation. The flexibility this provides is particularly relevant
- when running within Application Server environments where threads
- should not be created directly by the application itself. For such
- cases, Spring provides a
- TimerManagerTaskScheduler that delegates to a
- CommonJ TimerManager instance, typically configured with a JNDI-lookup.
-
+
+ TaskScheduler
+ implementations
- A simpler alternative, the
- ThreadPoolTaskScheduler, can be used whenever
- external thread management is not a requirement. Internally, it
- delegates to a ScheduledExecutorService
- instance. ThreadPoolTaskScheduler actually
- implements Spring's TaskExecutor
- interface as well, so that a single instance can be used for
- asynchronous execution as soon as possible as well
- as scheduled, and potentially recurring, executions.
-
-
+ As with Spring's TaskExecutor
+ abstraction, the primary benefit of the
+ TaskScheduler is that code relying on
+ scheduling behavior need not be coupled to a particular scheduler
+ implementation. The flexibility this provides is particularly relevant
+ when running within Application Server environments where threads should
+ not be created directly by the application itself. For such cases,
+ Spring provides a TimerManagerTaskScheduler that
+ delegates to a CommonJ TimerManager instance, typically configured with
+ a JNDI-lookup.
-
- The Task Namespace
+ A simpler alternative, the
+ ThreadPoolTaskScheduler, can be used whenever
+ external thread management is not a requirement. Internally, it
+ delegates to a ScheduledExecutorService
+ instance. ThreadPoolTaskScheduler actually
+ implements Spring's TaskExecutor
+ interface as well, so that a single instance can be used for
+ asynchronous execution as soon as possible as well
+ as scheduled, and potentially recurring, executions.
+
+
- Beginning with Spring 3.0, there is an XML namespace for configuring
- TaskExecutor and
- TaskScheduler instances. It also provides a
- convenient way to configure tasks to be scheduled with a trigger.
+
+ The Task Namespace
-
- The 'scheduler' element
- The following element will create a
- ThreadPoolTaskScheduler instance with the
- specified thread pool size.
- ]]>
+ Beginning with Spring 3.0, there is an XML namespace for configuring
+ TaskExecutor and
+ TaskScheduler instances. It also provides a
+ convenient way to configure tasks to be scheduled with a trigger.
- The value provided for the 'id' attribute will be used as the
- prefix for thread names within the pool. The 'scheduler' element is
- relatively straightforward. If you do not provide a 'pool-size' attribute,
- the default thread pool will only have a single thread. There are no
- other configuration options for the scheduler.
-
+
+ The 'scheduler' element
-
- The 'executor' element
- The following will create a
- ThreadPoolTaskExecutor instance:
- ]]>
-
+ The following element will create a
+ ThreadPoolTaskScheduler instance with the
+ specified thread pool size.
- As with the scheduler above, the value provided for the 'id'
- attribute will be used as the prefix for thread names within the pool.
- As far as the pool size is concerned, the 'executor' element supports
- more configuration options than the 'scheduler' element. For one thing,
- the thread pool for a ThreadPoolTaskExecutor is
- itself more configurable. Rather than just a single size, an executor's
- thread pool may have different values for the core
- and the max size. If a single value is provided
- then the executor will have a fixed-size thread pool (the core and max
- sizes are the same). However, the 'executor' element's 'pool-size' attribute
- also accepts a range in the form of "min-max".
- <task:scheduler id="scheduler" pool-size="10"/>
+
+ The value provided for the 'id' attribute will be used as the
+ prefix for thread names within the pool. The 'scheduler' element is
+ relatively straightforward. If you do not provide a 'pool-size'
+ attribute, the default thread pool will only have a single thread. There
+ are no other configuration options for the scheduler.
+
+
+
+ The 'executor' element
+
+ The following will create a
+ ThreadPoolTaskExecutor instance: <task:executor id="executor" pool-size="10"/>
+
+ As with the scheduler above, the value provided for the 'id'
+ attribute will be used as the prefix for thread names within the pool.
+ As far as the pool size is concerned, the 'executor' element supports
+ more configuration options than the 'scheduler' element. For one thing,
+ the thread pool for a ThreadPoolTaskExecutor is
+ itself more configurable. Rather than just a single size, an executor's
+ thread pool may have different values for the core
+ and the max size. If a single value is provided
+ then the executor will have a fixed-size thread pool (the core and max
+ sizes are the same). However, the 'executor' element's 'pool-size'
+ attribute also accepts a range in the form of "min-max". <task:executor id="executorWithPoolSizeRange"
pool-size="5-25"
- queue-capacity="100"/>]]>
-
+ queue-capacity="100"/>
- As you can see from that configuration, a 'queue-capacity' value
- has also been provided. The configuration of the thread pool should
- also be considered in light of the executor's queue capacity. For the
- full description of the relationship between pool size and queue
- capacity, consult the documentation for
- ThreadPoolExecutor.
- The main idea is that when a task is submitted, the executor will first
- try to use a free thread if the number of active threads is currently
- less than the core size. If the core size has been reached, then the
- task will be added to the queue as long as its capacity has not yet
- been reached. Only then, if the queue's capacity
- has been reached, will the executor create a new
- thread beyond the core size. If the max size has also been reached,
- then the executor will reject the task.
+ As you can see from that configuration, a 'queue-capacity' value
+ has also been provided. The configuration of the thread pool should also
+ be considered in light of the executor's queue capacity. For the full
+ description of the relationship between pool size and queue capacity,
+ consult the documentation for ThreadPoolExecutor.
+ The main idea is that when a task is submitted, the executor will first
+ try to use a free thread if the number of active threads is currently
+ less than the core size. If the core size has been reached, then the
+ task will be added to the queue as long as its capacity has not yet been
+ reached. Only then, if the queue's capacity has
+ been reached, will the executor create a new thread beyond the core
+ size. If the max size has also been reached, then the executor will
+ reject the task.
- By default, the queue is unbounded, but this
- is rarely the desired configuration, because it can lead to
- OutOfMemoryErrors if enough tasks are added to
- that queue while all pool threads are busy. Furthermore, if the queue
- is unbounded, then the max size has no effect at all. Since the
- executor will always try the queue before creating a new thread beyond
- the core size, a queue must have a finite capacity for the thread pool
- to grow beyond the core size (this is why a fixed size
- pool is the only sensible case when using an unbounded queue).
+ By default, the queue is unbounded, but this
+ is rarely the desired configuration, because it can lead to
+ OutOfMemoryErrors if enough tasks are added to
+ that queue while all pool threads are busy. Furthermore, if the queue is
+ unbounded, then the max size has no effect at all. Since the executor
+ will always try the queue before creating a new thread beyond the core
+ size, a queue must have a finite capacity for the thread pool to grow
+ beyond the core size (this is why a fixed size pool
+ is the only sensible case when using an unbounded queue).
- In a moment, we will review the effects of the keep-alive setting
- which adds yet another factor to consider when providing a pool size
- configuration. First, let's consider the case, as mentioned above, when
- a task is rejected. By default, when a task is rejected, a thread pool
- executor will throw a TaskRejectedException.
- However, the rejection policy is actually configurable. The exception
- is thrown when using the default rejection policy which is the
- AbortPolicy implementation. For applications
- where some tasks can be skipped under heavy load, either the
- DiscardPolicy or
- DiscardOldestPolicy may be configured instead.
- Another option that works well for applications that need to throttle
- the submitted tasks under heavy load is the
- CallerRunsPolicy. Instead of throwing an
- exception or discarding tasks, that policy will simply force the thread
- that is calling the submit method to run the task itself. The idea is
- that such a caller will be busy while running that task and not able to
- submit other tasks immediately. Therefore it provides a simple way to
- throttle the incoming load while maintaining the limits of the thread
- pool and queue. Typically this allows the executor to "catch up" on the
- tasks it is handling and thereby frees up some capacity on the queue,
- in the pool, or both. Any of these options can be chosen from an
- enumeration of values available for the 'rejection-policy' attribute on
- the 'executor' element.
- In a moment, we will review the effects of the keep-alive setting
+ which adds yet another factor to consider when providing a pool size
+ configuration. First, let's consider the case, as mentioned above, when
+ a task is rejected. By default, when a task is rejected, a thread pool
+ executor will throw a TaskRejectedException.
+ However, the rejection policy is actually configurable. The exception is
+ thrown when using the default rejection policy which is the
+ AbortPolicy implementation. For applications
+ where some tasks can be skipped under heavy load, either the
+ DiscardPolicy or
+ DiscardOldestPolicy may be configured instead.
+ Another option that works well for applications that need to throttle
+ the submitted tasks under heavy load is the
+ CallerRunsPolicy. Instead of throwing an
+ exception or discarding tasks, that policy will simply force the thread
+ that is calling the submit method to run the task itself. The idea is
+ that such a caller will be busy while running that task and not able to
+ submit other tasks immediately. Therefore it provides a simple way to
+ throttle the incoming load while maintaining the limits of the thread
+ pool and queue. Typically this allows the executor to "catch up" on the
+ tasks it is handling and thereby frees up some capacity on the queue, in
+ the pool, or both. Any of these options can be chosen from an
+ enumeration of values available for the 'rejection-policy' attribute on
+ the 'executor' element.
+
+ <task:executor id="executorWithCallerRunsPolicy"
pool-size="5-25"
queue-capacity="100"
- rejection-policy="CALLER_RUNS"/>]]>
-
+ rejection-policy="CALLER_RUNS"/>
+
-
- The 'scheduled-tasks' element
+
+ The 'scheduled-tasks' element
- The most powerful feature of Spring's task namespace is the
- support for configuring tasks to be scheduled within a Spring
- Application Context. This follows an approach similar to other
- "method-invokers" in Spring, such as that provided by the JMS namespace
- for configuring Message-driven POJOs. Basically a "ref" attribute can
- point to any Spring-managed object, and the "method" attribute provides
- the name of a method to be invoked on that object. Here is a simple
- example.
-
-
-
+ The most powerful feature of Spring's task namespace is the
+ support for configuring tasks to be scheduled within a Spring
+ Application Context. This follows an approach similar to other
+ "method-invokers" in Spring, such as that provided by the JMS namespace
+ for configuring Message-driven POJOs. Basically a "ref" attribute can
+ point to any Spring-managed object, and the "method" attribute provides
+ the name of a method to be invoked on that object. Here is a simple
+ example.
-]]>
+ <task:scheduled-tasks scheduler="myScheduler">
+ <task:scheduled ref="someObject" method="someMethod" fixed-delay="5000"/>
+</task:scheduled-tasks>
- As you can see, the scheduler is referenced by the outer element,
- and each individual task includes the configuration of its trigger
- metadata. In the preceding example, that metadata defines a periodic
- trigger with a fixed delay. It could also be configured with a
- "fixed-rate", or for more control, a "cron" attribute could be provided
- instead. Here's an example featuring these other options.
-
-
-
-
+<task:scheduler id="myScheduler" pool-size="10"/>
-]]>
-
-
+ As you can see, the scheduler is referenced by the outer element,
+ and each individual task includes the configuration of its trigger
+ metadata. In the preceding example, that metadata defines a periodic
+ trigger with a fixed delay. It could also be configured with a
+ "fixed-rate", or for more control, a "cron" attribute could be provided
+ instead. Here's an example featuring these other options.
-
- Annotation Support for Scheduling and Asynchronous Execution
+ <task:scheduled-tasks scheduler="myScheduler">
+ <task:scheduled ref="someObject" method="someMethod" fixed-rate="5000"/>
+ <task:scheduled ref="anotherObject" method="anotherMethod" cron="*/5 * * * * MON-FRI"/>
+</task:scheduled-tasks>
- Spring 3.0 also adds annotation support for both task scheduling
- and asynchronous method execution.
+<task:scheduler id="myScheduler" pool-size="10"/>
+
+
-
- The @Scheduled Annotation
+
+ Annotation Support for Scheduling and Asynchronous
+ Execution
- The @Scheduled annotation can be added to a method along with
- trigger metadata. For example, the following method would be invoked
- every 5 seconds with a fixed delay, meaning that the period will be
- measured from the completion time of each preceding invocation.
- Spring 3.0 also adds annotation support for both task scheduling and
+ asynchronous method execution.
+
+
+ The @Scheduled Annotation
+
+ The @Scheduled annotation can be added to a method along with
+ trigger metadata. For example, the following method would be invoked
+ every 5 seconds with a fixed delay, meaning that the period will be
+ measured from the completion time of each preceding invocation.
+
+ @Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
-}]]>
- If a fixed rate execution is desired, simply change the property
- name specified within the annotation. The following would be executed
- every 5 seconds measured between the successive start times of each
- invocation.
-
+
+ If a fixed rate execution is desired, simply change the property
+ name specified within the annotation. The following would be executed
+ every 5 seconds measured between the successive start times of each
+ invocation.
+
+ @Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
-}]]>
- If simple periodic scheduling is not expressive enough, then a
- cron expression may be provided. For example, the following will only
- execute on weekdays.
-
+
+ If simple periodic scheduling is not expressive enough, then a
+ cron expression may be provided. For example, the following will only
+ execute on weekdays.
+
+ @Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
-}]]>
- Notice that the methods to be scheduled must have void returns
- and must not expect any arguments. If the method needs to interact with
- other objects from the Application Context, then those would typically
- have been provided through dependency injection.
+}
-
- Make sure that you are not initializing multiple instances
- of the same @Scheduled annotation class at runtime, unless you do
- want to schedule callbacks to each such instance. Related to this,
- make sure that you do not use @Configurable on bean classes which
- are annotated with @Scheduled and registered as regular Spring beans
- with the container: You would get double initialization otherwise,
- once through the container and once through the @Configurable aspect,
- with the consequence of each @Scheduled method being invoked twice.
-
-
+ Notice that the methods to be scheduled must have void returns and
+ must not expect any arguments. If the method needs to interact with
+ other objects from the Application Context, then those would typically
+ have been provided through dependency injection.
-
- The @Async Annotation
+
+ Make sure that you are not initializing multiple instances of
+ the same @Scheduled annotation class at runtime, unless you do want to
+ schedule callbacks to each such instance. Related to this, make sure
+ that you do not use @Configurable on bean classes which are annotated
+ with @Scheduled and registered as regular Spring beans with the
+ container: You would get double initialization otherwise, once through
+ the container and once through the @Configurable aspect, with the
+ consequence of each @Scheduled method being invoked twice.
+
+
- The @Async annotation can be provided on a method so that
- invocation of that method will occur asynchronously. In other words,
- the caller will return immediately upon invocation and the actual
- execution of the method will occur in a task that has been submitted to
- a Spring TaskExecutor. In the simplest case, the annotation may be
- applied to a void-returning method.
+
+ The @Async Annotation
- The @Async annotation can be provided on a method so that
+ invocation of that method will occur asynchronously. In other words, the
+ caller will return immediately upon invocation and the actual execution
+ of the method will occur in a task that has been submitted to a Spring
+ TaskExecutor. In the simplest case, the annotation may be applied to a
+ void-returning method.
+
+ @Async
void doSomething() {
// this will be executed asynchronously
-}]]>
+}
- Unlike the methods annotated with the @Scheduled annotation,
- these methods can expect arguments, because they will be invoked
- in the "normal" way by callers at runtime rather than from a
- scheduled task being managed by the container. For example, the
- following is a legitimate application of the @Async annotation.
-
- Unlike the methods annotated with the @Scheduled annotation, these
+ methods can expect arguments, because they will be invoked in the
+ "normal" way by callers at runtime rather than from a scheduled task
+ being managed by the container. For example, the following is a
+ legitimate application of the @Async annotation.
+
+ @Async
void doSomething(String s) {
// this will be executed asynchronously
-}]]>
+}
- Even methods that return a value can be invoked asynchronously.
- However, such methods are required to have a Future typed return value.
- This still provides the benefit of asynchronous execution so that the
- caller can perform other tasks prior to calling 'get()' on that Future.
-
- returnSomething(int i) {
+ Even methods that return a value can be invoked asynchronously.
+ However, such methods are required to have a Future typed return value.
+ This still provides the benefit of asynchronous execution so that the
+ caller can perform other tasks prior to calling 'get()' on that
+ Future.
+
+ @Async
+Future<String> returnSomething(int i) {
// this will be executed asynchronously
-}]]>
-
+}
+
-
- The <annotation-driven> Element
+
+ The <annotation-driven> Element
- To enable both @Scheduled and @Async annotations, simply
- include the 'annotation-driven' element from the task namespace in
- your configuration.
-
+ To enable both @Scheduled and @Async annotations, simply include
+ the 'annotation-driven' element from the task namespace in your
+ configuration.
-
+ <task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
-}]]>
+<task:executor id="myExecutor" pool-size="5"/>
- Notice that an executor reference is provided for handling
- those tasks that correspond to methods with the @Async annotation,
- and the scheduler reference is provided for managing those methods
- annotated with @Scheduled.
-
-
+<task:scheduler id="myScheduler" pool-size="10"/>}
-
- Using the OpenSymphony Quartz Scheduler
- Quartz uses Trigger, Job and
- JobDetail objects to realize scheduling of all kinds of jobs.
- For the basic concepts behind Quartz, have a look at
- . For convenience purposes,
- Spring offers a couple of classes that simplify the usage of Quartz within
- Spring-based applications.
-
-
- Using the JobDetailBean
-
- JobDetail objects contain all information needed to
- run a job. The Spring Framework provides a JobDetailBean
- that makes the JobDetail more of an actual JavaBean
- with sensible defaults. Let's have a look at an example:
-
-
-
-
-
-
-]]>
- The job detail bean has all information it needs to run the job (ExampleJob).
- The timeout is specified in the job data map. The job data map is
- available through the JobExecutionContext
- (passed to you at execution time), but the JobDetailBean
- also maps the properties from the job data map to properties of the actual job.
- So in this case, if the ExampleJob contains a property
- named timeout, the JobDetailBean will
- automatically apply it:
- Notice that an executor reference is provided for handling those
+ tasks that correspond to methods with the @Async annotation, and the
+ scheduler reference is provided for managing those methods annotated
+ with @Scheduled.
+
+
+
+
+ Using the OpenSymphony Quartz Scheduler
+
+ Quartz uses Trigger,
+ Job and JobDetail objects to
+ realize scheduling of all kinds of jobs. For the basic concepts behind
+ Quartz, have a look at . For convenience
+ purposes, Spring offers a couple of classes that simplify the usage of
+ Quartz within Spring-based applications.
+
+
+ Using the JobDetailBean
+
+ JobDetail objects contain all information
+ needed to run a job. The Spring Framework provides a
+ JobDetailBean that makes the
+ JobDetail more of an actual JavaBean with
+ sensible defaults. Let's have a look at an example:
+
+
+<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
+ <property name="jobClass" value="example.ExampleJob" />
+ <property name="jobDataAsMap">
+ <map>
+ <entry key="timeout" value="5" />
+ </map>
+ </property>
+</bean>
+
+ The job detail bean has all information it needs to run the job
+ (ExampleJob). The timeout is specified in the job
+ data map. The job data map is available through the
+ JobExecutionContext (passed to you at execution
+ time), but the JobDetailBean also maps the
+ properties from the job data map to properties of the actual job. So in
+ this case, if the ExampleJob contains a property
+ named timeout, the
+ JobDetailBean will automatically apply it:
+
+ package example;
public class ExampleJob extends QuartzJobBean {
@@ -671,123 +661,152 @@ public class ExampleJob extends QuartzJobBean {
}
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
- ]]>// do the actual work// do the actual work
}
-}]]>
- All additional settings from the job detail bean are of course available to you as well.
- Note: Using the name and group properties,
- you can modify the name and the group of the job, respectively. By default, the name of
- the job matches the bean name of the job detail bean (in the example above, this is
- exampleJob).
-
-
- Using the MethodInvokingJobDetailFactoryBean
- Often you just need to invoke a method on a specific object. Using the
- MethodInvokingJobDetailFactoryBean you can do exactly this:
-
-
-
-]]>
- The above example will result in the doIt method being called on the
- exampleBusinessObject method (see below):
-
+
+ All additional settings from the job detail bean are of course
+ available to you as well.
+
+ Note: Using the name and
+ group properties, you can modify the name and the
+ group of the job, respectively. By default, the name of the job matches
+ the bean name of the job detail bean (in the example above, this is
+ exampleJob).
+
+
+
+ Using the
+ MethodInvokingJobDetailFactoryBean
+
+ Often you just need to invoke a method on a specific object. Using
+ the MethodInvokingJobDetailFactoryBean you can do
+ exactly this:
+
+ <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
+ <property name="targetObject" ref="exampleBusinessObject" />
+ <property name="targetMethod" value="doIt" />
+</bean>
+
+ The above example will result in the doIt
+ method being called on the exampleBusinessObject
+ method (see below):
+
+ public class ExampleBusinessObject {
- ]]>// properties and collaborators// properties and collaborators
public void doIt() {
- ]]>// do the actual work// do the actual work
}
-}]]>
+}
- ]]>
- Using the MethodInvokingJobDetailFactoryBean, you don't need to
- create one-line jobs that just invoke a method, and you only need to create the actual
- business object and wire up the detail object.
- By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering
- with each other. If you specify two triggers for the same JobDetail,
- it might be possible that before the first job has finished, the second one will start.
- If JobDetail classes implement the
- Stateful interface, this won't happen. The second job
- will not start before the first one has finished. To make jobs resulting from the
- MethodInvokingJobDetailFactoryBean non-concurrent, set the
- concurrent flag to false.
-
-
-
-
-]]>
-
- By default, jobs will run in a concurrent fashion.
-
-
-
- Wiring up jobs using triggers and the SchedulerFactoryBean
-
- We've created job details and jobs. We've also reviewed the convenience bean
- that allows you to invoke a method on a specific object. Of course, we still need
- to schedule the jobs themselves. This is done using triggers and a
- SchedulerFactoryBean. Several triggers are available
- within Quartz. Spring offers two subclassed triggers with convenient defaults:
- CronTriggerBean and SimpleTriggerBean.
-
-
- Triggers need to be scheduled. Spring offers a SchedulerFactoryBean
- that exposes triggers to be set as properties. SchedulerFactoryBean
- schedules the actual jobs with those triggers.
-
- Find below a couple of examples:
-
-
-
-
-
-
-
-
+
+<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/>
-
-
-
-
-]]>
- Now we've set up two triggers, one running every 50 seconds with a starting delay of
- 10 seconds and one every morning at 6 AM. To finalize everything, we need to set up the
- SchedulerFactoryBean:
-
-
-
-
-
-
-
-]]>
-
- More properties are available for the SchedulerFactoryBean for you
- to set, such as the calendars used by the job details, properties to customize Quartz with,
- etc. Have a look at the
- SchedulerFactoryBean Javadoc
- for more information.
-
-
-
+ Using the
+ MethodInvokingJobDetailFactoryBean, you don't
+ need to create one-line jobs that just invoke a method, and you only
+ need to create the actual business object and wire up the detail
+ object.
-
- Using JDK Timer support
-
- The other way to schedule jobs in Spring is to use JDK
- Timer objects. You can create custom timers or
- use the timer that invokes methods. Wiring timers is done using the
- TimerFactoryBean.
-
-
- Creating custom timers
-
- Using the TimerTask you can create customer
- timer tasks, similar to Quartz jobs:
-
- By default, Quartz Jobs are stateless, resulting in the
+ possibility of jobs interfering with each other. If you specify two
+ triggers for the same JobDetail, it might be
+ possible that before the first job has finished, the second one will
+ start. If JobDetail classes implement the
+ Stateful interface, this won't happen.
+ The second job will not start before the first one has finished. To make
+ jobs resulting from the
+ MethodInvokingJobDetailFactoryBean
+ non-concurrent, set the concurrent flag to
+ false.
+
+
+<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
+ <property name="targetObject" ref="exampleBusinessObject" />
+ <property name="targetMethod" value="doIt" />
+ <property name="concurrent" value="false" />
+</bean>
+
+
+ By default, jobs will run in a concurrent fashion.
+
+
+
+
+ Wiring up jobs using triggers and the
+ SchedulerFactoryBean
+
+ We've created job details and jobs. We've also reviewed the
+ convenience bean that allows you to invoke a method on a specific
+ object. Of course, we still need to schedule the jobs themselves. This
+ is done using triggers and a
+ SchedulerFactoryBean. Several triggers are
+ available within Quartz. Spring offers two subclassed triggers with
+ convenient defaults: CronTriggerBean and
+ SimpleTriggerBean.
+
+ Triggers need to be scheduled. Spring offers a
+ SchedulerFactoryBean that exposes triggers to be
+ set as properties. SchedulerFactoryBean schedules
+ the actual jobs with those triggers.
+
+ Find below a couple of examples:
+
+ <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
+ <!-- see the example of method invoking job above -->
+ <property name="jobDetail" ref="jobDetail" />
+ <!-- 10 seconds -->
+ <property name="startDelay" value="10000" />
+ <!-- repeat every 50 seconds -->
+ <property name="repeatInterval" value="50000" />
+</bean>
+
+<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+ <property name="jobDetail" ref="exampleJob" />
+ <!-- run every morning at 6 AM -->
+ <property name="cronExpression" value="0 0 6 * * ?" />
+</bean>
+
+ Now we've set up two triggers, one running every 50 seconds with a
+ starting delay of 10 seconds and one every morning at 6 AM. To finalize
+ everything, we need to set up the
+ SchedulerFactoryBean:
+
+ <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
+ <property name="triggers">
+ <list>
+ <ref bean="cronTrigger" />
+ <ref bean="simpleTrigger" />
+ </list>
+ </property>
+</bean>
+
+ More properties are available for the
+ SchedulerFactoryBean for you to set, such as the
+ calendars used by the job details, properties to customize Quartz with,
+ etc. Have a look at the SchedulerFactoryBean
+ Javadoc for more information.
+
+
+
+
+ Using JDK Timer support
+
+ The other way to schedule jobs in Spring is to use JDK
+ Timer objects. You can create custom timers or use
+ the timer that invokes methods. Wiring timers is done using the
+ TimerFactoryBean.
+
+
+ Creating custom timers
+
+ Using the TimerTask you can create customer
+ timer tasks, similar to Quartz jobs:
+
+ public class CheckEmailAddresses extends TimerTask {
private List emailAddresses;
@@ -796,78 +815,86 @@ public class ExampleJob extends QuartzJobBean {
}
public void run() {
- ]]>// iterate over all email addresses and archive them// iterate over all email addresses and archive them
}
-}]]>
-
- Wiring it up is simple:
-
-
-
-
- test@springframework.org
- foo@bar.com
- john@doe.net
-
-
-
+}
-
- ]]><!-- wait 10 seconds before starting repeated execution -->
- ]]><!-- run every 50 seconds -->
-
-]]>
-
-
- Note that letting the task only run once can be done by changing the
- period property to 0 (or a negative value).
-
-
-
-
- Using the MethodInvokingTimerTaskFactoryBean
-
- Similar to the Quartz support, the Timer support also features
- a component that allows you to periodically invoke a method:
-
-
-
-
-]]>
-
- The above example will result in the doIt method being called on the
- exampleBusinessObject (see below):
-
- Wiring it up is simple:
+
+ <bean id="checkEmail" class="examples.CheckEmailAddress">
+ <property name="emailAddresses">
+ <list>
+ <value>test@springframework.org</value>
+ <value>foo@bar.com</value>
+ <value>john@doe.net</value>
+ </list>
+ </property>
+</bean>
+
+<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="checkEmail" />
+</bean>
+
+ Note that letting the task only run once can be done by
+ changing the period property to 0 (or a negative
+ value).
+
+
+
+ Using the
+ MethodInvokingTimerTaskFactoryBean
+
+ Similar to the Quartz support, the Timer
+ support also features a component that allows you to periodically invoke
+ a method:
+
+ <bean id="doIt" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
+ <property name="targetObject" ref="exampleBusinessObject" />
+ <property name="targetMethod" value="doIt" />
+</bean>
+
+ The above example will result in the doIt
+ method being called on the exampleBusinessObject (see
+ below):
+
+ public class BusinessObject {
- ]]>// properties and collaborators// properties and collaborators
public void doIt() {
- ]]>// do the actual work// do the actual work
}
-}]]>
- Changing the timerTask reference of the
- ScheduledTimerTask example to the bean doIt
- will result in the doIt method being executed on a fixed schedule.
-
-
- Wrapping up: setting up the tasks using the TimerFactoryBean
- The TimerFactoryBean is similar to the Quartz
- SchedulerFactoryBean in that it serves the same
- purpose: setting up the actual scheduling. The TimerFactoryBean
- sets up an actual Timer and schedules the tasks it has
- references to. You can specify whether or not daemon threads should be used.
-
-
-
- ]]><!-- see the example above -->
-
-
-]]>
-
-
+}
-
+ Changing the timerTask reference of the
+ ScheduledTimerTask example to the bean
+ doIt will result in the doIt
+ method being executed on a fixed schedule.
+
+
+
+ Wrapping up: setting up the tasks using the
+ TimerFactoryBean
+
+ The TimerFactoryBean is similar to the
+ Quartz SchedulerFactoryBean in that it serves the
+ same purpose: setting up the actual scheduling. The
+ TimerFactoryBean sets up an actual
+ Timer and schedules the tasks it has references
+ to. You can specify whether or not daemon threads should be used.
+
+ <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
+ <property name="scheduledTimerTasks">
+ <list>
+ <!-- see the example above -->
+ <ref bean="scheduledTask" />
+ </list>
+ </property>
+</bean>
+
+
+
\ No newline at end of file