KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > core > task > SimpleAsyncTaskExecutor


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.core.task;
18
19 import java.io.Serializable JavaDoc;
20
21 import org.springframework.util.Assert;
22 import org.springframework.util.ClassUtils;
23 import org.springframework.util.ConcurrencyThrottleSupport;
24 import org.springframework.util.CustomizableThreadCreator;
25
26 /**
27  * TaskExecutor implementation that fires up a new Thread for each task,
28  * executing it asynchronously.
29  *
30  * <p>Supports limiting concurrent threads through the "concurrencyLimit"
31  * bean property. By default, the number of concurrent threads is unlimited.
32  *
33  * <p><b>NOTE: This implementation does not reuse threads!</b> Consider a
34  * thread-pooling TaskExecutor implementation instead, in particular for
35  * executing a large number of short-lived tasks.
36  *
37  * @author Juergen Hoeller
38  * @since 2.0
39  * @see #setConcurrencyLimit
40  * @see SyncTaskExecutor
41  * @see org.springframework.scheduling.timer.TimerTaskExecutor
42  * @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
43  * @see org.springframework.scheduling.commonj.WorkManagerTaskExecutor
44  */

45 public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator implements AsyncTaskExecutor, Serializable JavaDoc {
46
47     /**
48      * Default thread name prefix: "SimpleAsyncTaskExecutor-".
49      * @deprecated as of Spring 2.0.3, since the default thread name prefix
50      * is now taken from the concrete class (could be a subclass)
51      */

52     public static final String JavaDoc DEFAULT_THREAD_NAME_PREFIX =
53             ClassUtils.getShortName(SimpleAsyncTaskExecutor.class) + "-";
54
55     /**
56      * Permit any number of concurrent invocations: that is, don't throttle concurrency.
57      */

58     public static final int UNBOUNDED_CONCURRENCY = ConcurrencyThrottleSupport.UNBOUNDED_CONCURRENCY;
59
60     /**
61      * Switch concurrency 'off': that is, don't allow any concurrent invocations.
62      */

63     public static final int NO_CONCURRENCY = ConcurrencyThrottleSupport.NO_CONCURRENCY;
64
65
66     /**
67      * Internal concurrency throttle used by this executor.
68      */

69     private final ConcurrencyThrottleAdapter concurrencyThrottle = new ConcurrencyThrottleAdapter();
70
71
72     /**
73      * Create a new SimpleAsyncTaskExecutor with default thread name prefix.
74      */

75     public SimpleAsyncTaskExecutor() {
76         super();
77     }
78
79     /**
80      * Create a new SimpleAsyncTaskExecutor with the given thread name prefix.
81      * @param threadNamePrefix the prefix to use for the names of newly created threads
82      */

83     public SimpleAsyncTaskExecutor(String JavaDoc threadNamePrefix) {
84         super(threadNamePrefix);
85     }
86
87
88     /**
89      * Set the maximum number of parallel accesses allowed.
90      * -1 indicates no concurrency limit at all.
91      * <p>In principle, this limit can be changed at runtime,
92      * although it is generally designed as a config time setting.
93      * NOTE: Do not switch between -1 and any concrete limit at runtime,
94      * as this will lead to inconsistent concurrency counts: A limit
95      * of -1 effectively turns off concurrency counting completely.
96      * @see #UNBOUNDED_CONCURRENCY
97      */

98     public void setConcurrencyLimit(int concurrencyLimit) {
99         this.concurrencyThrottle.setConcurrencyLimit(concurrencyLimit);
100     }
101
102     /**
103      * Return the maximum number of parallel accesses allowed.
104      */

105     public int getConcurrencyLimit() {
106         return this.concurrencyThrottle.getConcurrencyLimit();
107     }
108
109     /**
110      * Return whether this throttle is currently active.
111      * @return <code>true</code> if the concurrency limit for this instance is active
112      * @see #getConcurrencyLimit()
113      * @see #setConcurrencyLimit
114      */

115     public boolean isThrottleActive() {
116         return this.concurrencyThrottle.isThrottleActive();
117     }
118
119
120     /**
121      * Executes the given task, within a concurrency throttle
122      * if configured (through the superclass's settings).
123      * @see #doExecute(Runnable)
124      */

125     public void execute(Runnable JavaDoc task) {
126         execute(task, TIMEOUT_INDEFINITE);
127     }
128
129     /**
130      * Executes the given task, within a concurrency throttle
131      * if configured (through the superclass's settings).
132      * <p>Executes urgent tasks (with 'immediate' timeout) directly,
133      * bypassing the concurrency throttle (if active). All other
134      * tasks are subject to throttling.
135      * @see #TIMEOUT_IMMEDIATE
136      * @see #doExecute(Runnable)
137      */

138     public void execute(Runnable JavaDoc task, long startTimeout) {
139         Assert.notNull(task, "Runnable must not be null");
140         if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
141             this.concurrencyThrottle.beforeAccess();
142             doExecute(new ConcurrencyThrottlingRunnable(task));
143         }
144         else {
145             doExecute(task);
146         }
147     }
148
149     /**
150      * Template method for the actual execution of a task.
151      * <p>The default implementation creates a new Thread and starts it.
152      * @param task the Runnable to execute
153      * @see #createThread
154      * @see java.lang.Thread#start()
155      */

156     protected void doExecute(Runnable JavaDoc task) {
157         createThread(task).start();
158     }
159
160
161     /**
162      * Subclass of the general ConcurrencyThrottleSupport class,
163      * making <code>beforeAccess()</code> and <code>afterAccess()</code>
164      * visible to the surrounding class.
165      */

166     private static class ConcurrencyThrottleAdapter extends ConcurrencyThrottleSupport {
167
168         protected void beforeAccess() {
169             super.beforeAccess();
170         }
171
172         protected void afterAccess() {
173             super.afterAccess();
174         }
175     }
176
177
178     /**
179      * This Runnable calls <code>afterAccess()</code> after the
180      * target Runnable has finished its execution.
181      */

182     private class ConcurrencyThrottlingRunnable implements Runnable JavaDoc {
183
184         private final Runnable JavaDoc target;
185
186         public ConcurrencyThrottlingRunnable(Runnable JavaDoc target) {
187             this.target = target;
188         }
189
190         public void run() {
191             try {
192                 this.target.run();
193             }
194             finally {
195                 concurrencyThrottle.afterAccess();
196             }
197         }
198     }
199
200 }
201
Popular Tags