001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.spi;
018
019import java.util.List;
020import java.util.concurrent.ExecutorService;
021import java.util.concurrent.ScheduledExecutorService;
022
023import org.apache.camel.ShutdownableService;
024import org.apache.camel.StaticService;
025
026/**
027 * Strategy to create thread pools.
028 * <p/>
029 * This manager is pluggable so you can plugin a custom provider, for example if you want to leverage
030 * the WorkManager for a JEE server.
031 * <p/>
032 * You may want to just implement a custom {@link ThreadPoolFactory} and rely on the
033 * {@link org.apache.camel.impl.DefaultExecutorServiceManager}, if that is sufficient. The {@link ThreadPoolFactory}
034 * is always used for creating the actual thread pools. You can implement a custom {@link ThreadPoolFactory}
035 * to leverage the WorkManager for a JEE server.
036 * <p/>
037 * The {@link ThreadPoolFactory} has pure JDK API, where as this {@link ExecutorServiceManager} has Camel API
038 * concepts such as {@link ThreadPoolProfile}. Therefore it may be easier to only implement a custom
039 * {@link ThreadPoolFactory}.
040 * <p/>
041 * This manager has fine grained methods for creating various thread pools, however custom strategies
042 * do not have to exactly create those kind of pools. Feel free to return a shared or different kind of pool.
043 * <p/>
044 * If you use the <tt>newXXX</tt> methods to create thread pools, then Camel will by default take care of
045 * shutting down those created pools when {@link org.apache.camel.CamelContext} is shutting down.
046 * <p/>
047 * For more information about shutting down thread pools see the {@link #shutdown(java.util.concurrent.ExecutorService)}
048 * and {@link #shutdownNow(java.util.concurrent.ExecutorService)}, and {@link #getShutdownAwaitTermination()} methods.
049 * Notice the details about using a graceful shutdown at fist, and then falling back to aggressive shutdown in case
050 * of await termination timeout occurred.
051 *
052 * @see ThreadPoolFactory
053 */
054public interface ExecutorServiceManager extends ShutdownableService, StaticService {
055
056    /**
057     * Gets the {@link ThreadPoolFactory} to use for creating the thread pools.
058     *
059     * @return the thread pool factory
060     */
061    ThreadPoolFactory getThreadPoolFactory();
062
063    /**
064     * Sets a custom {@link ThreadPoolFactory} to use
065     *
066     * @param threadPoolFactory the thread pool factory
067     */
068    void setThreadPoolFactory(ThreadPoolFactory threadPoolFactory);
069
070    /**
071     * Creates a full thread name
072     *
073     * @param name name which is appended to the full thread name
074     * @return the full thread name
075     */
076    String resolveThreadName(String name);
077
078    /**
079     * Gets the thread pool profile by the given id
080     *
081     * @param id id of the thread pool profile to get
082     * @return the found profile, or <tt>null</tt> if not found
083     */
084    ThreadPoolProfile getThreadPoolProfile(String id);
085
086    /**
087     * Registers the given thread pool profile
088     *
089     * @param profile the profile
090     */
091    void registerThreadPoolProfile(ThreadPoolProfile profile);
092
093    /**
094     * Sets the default thread pool profile
095     *
096     * @param defaultThreadPoolProfile the new default thread pool profile
097     */
098    void setDefaultThreadPoolProfile(ThreadPoolProfile defaultThreadPoolProfile);
099
100    /**
101     * Gets the default thread pool profile
102     *
103     * @return the default profile which are newer <tt>null</tt>
104     */
105    ThreadPoolProfile getDefaultThreadPoolProfile();
106
107    /**
108     * Sets the thread name pattern used for creating the full thread name.
109     * <p/>
110     * The default pattern is: <tt>Camel (#camelId#) thread ##counter# - #name#</tt>
111     * <p/>
112     * Where <tt>#camelId#</tt> is the name of the {@link org.apache.camel.CamelContext}
113     * <br/>and <tt>#counter#</tt> is a unique incrementing counter.
114     * <br/>and <tt>#name#</tt> is the regular thread name.
115     * <br/>You can also use <tt>#longName#</tt> is the long thread name which can includes endpoint parameters etc.
116     *
117     * @param pattern the pattern
118     * @throws IllegalArgumentException if the pattern is invalid.
119     */
120    void setThreadNamePattern(String pattern) throws IllegalArgumentException;
121
122    /**
123     * Gets the thread name patter to use
124     *
125     * @return the pattern
126     */
127    String getThreadNamePattern();
128
129    /**
130     * Sets the time to wait for thread pools to shutdown orderly, when invoking the
131     * {@link #shutdown()} method.
132     * <p/>
133     * The default value is <tt>10000</tt> millis.
134     *
135     * @param timeInMillis time in millis.
136     */
137    void setShutdownAwaitTermination(long timeInMillis);
138
139    /**
140     * Gets the time to wait for thread pools to shutdown orderly, when invoking the
141     * {@link #shutdown()} method.
142     * <p/>
143     * The default value is <tt>10000</tt> millis.
144     *
145     * @return the timeout value
146     */
147    long getShutdownAwaitTermination();
148
149    /**
150     * Creates a new daemon thread with the given name.
151     *
152     * @param name     name which is appended to the thread name
153     * @param runnable a runnable to be executed by new thread instance
154     * @return the created thread
155     */
156    Thread newThread(String name, Runnable runnable);
157
158    /**
159     * Creates a new thread pool using the default thread pool profile.
160     *
161     * @param source the source object, usually it should be <tt>this</tt> passed in as parameter
162     * @param name   name which is appended to the thread name
163     * @return the created thread pool
164     */
165    ExecutorService newDefaultThreadPool(Object source, String name);
166
167    /**
168     * Creates a new scheduled thread pool using the default thread pool profile.
169     *
170     * @param source the source object, usually it should be <tt>this</tt> passed in as parameter
171     * @param name   name which is appended to the thread name
172     * @return the created thread pool
173     */
174    ScheduledExecutorService newDefaultScheduledThreadPool(Object source, String name);
175
176    /**
177     * Creates a new thread pool using the given profile
178     *
179     * @param source   the source object, usually it should be <tt>this</tt> passed in as parameter
180     * @param name     name which is appended to the thread name
181     * @param profile the profile with the thread pool settings to use
182     * @return the created thread pool
183     */
184    ExecutorService newThreadPool(Object source, String name, ThreadPoolProfile profile);
185
186    /**
187     * Creates a new thread pool using using the given profile id
188     *
189     * @param source    the source object, usually it should be <tt>this</tt> passed in as parameter
190     * @param name      name which is appended to the thread name
191     * @param profileId the id of the profile with the thread pool settings to use
192     * @return the created thread pool, or <tt>null</tt> if the thread pool profile could not be found
193     */
194    ExecutorService newThreadPool(Object source, String name, String profileId);
195
196    /**
197     * Creates a new thread pool.
198     * <p/>
199     * Will fallback and use values from the default thread pool profile for keep alive time, rejection policy
200     * and other parameters which cannot be specified.
201     *
202     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
203     * @param name        name which is appended to the thread name
204     * @param poolSize    the core pool size
205     * @param maxPoolSize the maximum pool size
206     * @return the created thread pool
207     */
208    ExecutorService newThreadPool(Object source, String name, int poolSize, int maxPoolSize);
209
210    /**
211     * Creates a new single-threaded thread pool. This is often used for background threads.
212     * <p/>
213     * Notice that there will always be a single thread in the pool. If you want the pool to be
214     * able to shrink to no threads, then use the <tt>newThreadPool</tt> method, and use
215     * 0 in core pool size, and 1 in max pool size.
216     *
217     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
218     * @param name        name which is appended to the thread name
219     * @return the created thread pool
220     */
221    ExecutorService newSingleThreadExecutor(Object source, String name);
222
223    /**
224     * Creates a new cached thread pool.
225     * <p/>
226     * <b>Important:</b> Using cached thread pool is discouraged as they have no upper bound and can overload the JVM.
227     *
228     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
229     * @param name        name which is appended to the thread name
230     * @return the created thread pool
231     */
232    ExecutorService newCachedThreadPool(Object source, String name);
233
234    /**
235     * Creates a new fixed thread pool.
236     *
237     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
238     * @param name        name which is appended to the thread name
239     * @param poolSize    the core pool size
240     * @return the created thread pool
241     */
242    ExecutorService newFixedThreadPool(Object source, String name, int poolSize);
243
244    /**
245     * Creates a new scheduled thread pool.
246     *
247     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
248     * @param name        name which is appended to the thread name
249     * @param poolSize    the core pool size
250     * @return the created thread pool
251     */
252    ScheduledExecutorService newScheduledThreadPool(Object source, String name, int poolSize);
253
254    /**
255     * Creates a new single-threaded thread pool. This is often used for background threads.
256     *
257     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
258     * @param name        name which is appended to the thread name
259     * @return the created thread pool
260     */
261    ScheduledExecutorService newSingleThreadScheduledExecutor(Object source, String name);
262    
263    /**
264     * Creates a new scheduled thread pool using a profile
265     *
266     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
267     * @param name        name which is appended to the thread name
268     * @param profile     the profile with the thread pool settings to use
269     * @return created thread pool
270     */
271    ScheduledExecutorService newScheduledThreadPool(Object source, String name, ThreadPoolProfile profile);
272
273    /**
274     * Creates a new scheduled thread pool using a profile id
275     *
276     * @param source      the source object, usually it should be <tt>this</tt> passed in as parameter
277     * @param name        name which is appended to the thread name
278     * @param profileId   the id of the profile with the thread pool settings to use
279     * @return created thread pool
280     */
281    ScheduledExecutorService newScheduledThreadPool(Object source, String name, String profileId);
282
283    /**
284     * Shutdown the given executor service (<b>not</b> graceful).
285     * <p/>
286     * This implementation will issues a regular shutdown of the executor service,
287     * ie calling {@link java.util.concurrent.ExecutorService#shutdown()} and return.
288     *
289     * @param executorService the executor service to shutdown
290     * @see java.util.concurrent.ExecutorService#shutdown()
291     */
292    void shutdown(ExecutorService executorService);
293
294    /**
295     * Shutdown the given executor service graceful at first, and then aggressively
296     * if the await termination timeout was hit.
297     * <p/>
298     * Will try to perform an orderly shutdown by giving the running threads
299     * time to complete tasks, before going more aggressively by doing a
300     * {@link #shutdownNow(java.util.concurrent.ExecutorService)} which
301     * forces a shutdown. The {@link #getShutdownAwaitTermination()}
302     * is used as timeout value waiting for orderly shutdown to
303     * complete normally, before going aggressively.
304     *
305     * @param executorService the executor service to shutdown
306     * @see java.util.concurrent.ExecutorService#shutdown()
307     * @see #getShutdownAwaitTermination()
308     */
309    void shutdownGraceful(ExecutorService executorService);
310
311    /**
312     * Shutdown the given executor service graceful at first, and then aggressively
313     * if the await termination timeout was hit.
314     * <p/>
315     * Will try to perform an orderly shutdown by giving the running threads
316     * time to complete tasks, before going more aggressively by doing a
317     * {@link #shutdownNow(java.util.concurrent.ExecutorService)} which
318     * forces a shutdown. The parameter <tt>shutdownAwaitTermination</tt>
319     * is used as timeout value waiting for orderly shutdown to
320     * complete normally, before going aggressively.
321     *
322     * @param executorService the executor service to shutdown
323     * @param shutdownAwaitTermination timeout in millis to wait for orderly shutdown
324     * @see java.util.concurrent.ExecutorService#shutdown()
325     */
326    void shutdownGraceful(ExecutorService executorService, long shutdownAwaitTermination);
327
328    /**
329     * Shutdown now the given executor service aggressively.
330     * <p/>
331     * This implementation will issues a regular shutdownNow of the executor service,
332     * ie calling {@link java.util.concurrent.ExecutorService#shutdownNow()} and return.
333     *
334     * @param executorService the executor service to shutdown now
335     * @return list of tasks that never commenced execution
336     * @see java.util.concurrent.ExecutorService#shutdownNow()
337     */
338    List<Runnable> shutdownNow(ExecutorService executorService);
339
340    /**
341     * Awaits the termination of the thread pool.
342     * <p/>
343     * This implementation will log every 2nd second at INFO level that we are waiting, so the end user
344     * can see we are not hanging in case it takes longer time to terminate the pool.
345     *
346     * @param executorService            the thread pool
347     * @param shutdownAwaitTermination   time in millis to use as timeout
348     * @return <tt>true</tt> if the pool is terminated, or <tt>false</tt> if we timed out
349     * @throws InterruptedException is thrown if we are interrupted during waiting
350     */
351    boolean awaitTermination(ExecutorService executorService, long shutdownAwaitTermination) throws InterruptedException;
352
353}