SpecialExecutors with LoggingThreadUncaughtExceptionHandler
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / concurrent / SpecialExecutors.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.util.concurrent;
10
11 import java.util.concurrent.ExecutorService;
12 import java.util.concurrent.TimeUnit;
13
14 /**
15  * Factory methods for creating {@link ExecutorService} instances with specific configurations.
16  *
17  * @author Thomas Pantelis
18  */
19 public final class SpecialExecutors {
20
21     private SpecialExecutors() {
22     }
23
24     /**
25      * Creates an ExecutorService with a specified bounded queue capacity that favors creating new
26      * threads over queuing, as the former is faster, so threads will only be reused when the thread
27      * limit is exceeded and tasks are queued. If the maximum queue capacity is reached, subsequent
28      * tasks will be rejected.
29      *
30      * <p>For example, if the maximum number of threads is 100 and 100 short-lived tasks are submitted
31      * within say 10 seconds, then 100 threads will be created and used - previously constructed
32      * idle threads will not be reused. This provides the fastest execution of the 100 tasks at the
33      * expense of memory and thread resource overhead. Therefore it is advisable to specify a
34      * relatively small thread limit (probably no more than 50).
35      *
36      * <p>Threads that have not been used for 15 seconds are terminated and removed from the pool.
37      * Thus, a pool that remains idle for long enough will not consume any resources.
38      *
39      * <p>If you need an executor with less memory and thread resource overhead where slower execution
40      * time is acceptable, consider using {@link #newBoundedCachedThreadPool }.
41      *
42      * @param maximumPoolSize
43      *            the maximum number of threads to allow in the pool. Threads will terminate after
44      *            being idle for 15 seconds.
45      * @param maximumQueueSize
46      *            the capacity of the queue.
47      * @param threadPrefix
48      *            the name prefix for threads created by this executor.
49      * @param loggerIdentity
50      *               the class to use as logger name for logging uncaught exceptions from the threads.
51      * @return a new ExecutorService with the specified configuration.
52      */
53     public static ExecutorService newBoundedFastThreadPool(int maximumPoolSize,
54             int maximumQueueSize, String threadPrefix, Class<?> loggerIdentity) {
55         return new FastThreadPoolExecutor(maximumPoolSize, maximumQueueSize, threadPrefix, loggerIdentity);
56     }
57
58     /**
59      * Deprecated variant.
60      * @deprecated Please use {@link #newBoundedFastThreadPool(int, int, String, Class)} instead.
61      */
62     @Deprecated
63     public static ExecutorService newBoundedFastThreadPool(int maximumPoolSize,
64             int maximumQueueSize, String threadPrefix) {
65         return newBoundedFastThreadPool(maximumPoolSize, maximumQueueSize, threadPrefix, SpecialExecutors.class);
66     }
67
68     /**
69      * Creates an ExecutorService similar to {@link #newBoundedFastThreadPool } except that it
70      * handles rejected tasks by running them in the same thread as the caller. Therefore if the
71      * queue is full, the caller submitting the task will be blocked until the task completes. In
72      * this manner, tasks are never rejected.
73      *
74      * @param maximumPoolSize
75      *            the maximum number of threads to allow in the pool. Threads will terminate after
76      *            being idle for 15 seconds.
77      * @param maximumQueueSize
78      *            the capacity of the queue.
79      * @param threadPrefix
80      *            the name prefix for threads created by this executor.
81      * @param loggerIdentity
82      *               the class to use as logger name for logging uncaught exceptions from the threads.
83      * @return a new ExecutorService with the specified configuration.
84      */
85     public static ExecutorService newBlockingBoundedFastThreadPool(int maximumPoolSize,
86             int maximumQueueSize, String threadPrefix, Class<?> loggerIdentity) {
87
88         FastThreadPoolExecutor executor = new FastThreadPoolExecutor(maximumPoolSize, maximumQueueSize, threadPrefix,
89                 loggerIdentity);
90         executor.setRejectedExecutionHandler(CountingRejectedExecutionHandler.newCallerRunsPolicy());
91         return executor;
92     }
93
94     /**
95      * Deprecated variant.
96      * @deprecated Please use {@link #newBlockingBoundedFastThreadPool(int, int, String, Class)} instead.
97      */
98     @Deprecated
99     public static ExecutorService newBlockingBoundedFastThreadPool(int maximumPoolSize,
100             int maximumQueueSize, String threadPrefix) {
101         return newBlockingBoundedFastThreadPool(maximumPoolSize, maximumQueueSize, threadPrefix,
102                 SpecialExecutors.class);
103     }
104
105     /**
106      * Creates an ExecutorService with a specified bounded queue capacity that favors reusing
107      * previously constructed threads, when they are available, over creating new threads. When a
108      * task is submitted, if no existing thread is available, a new thread will be created and added
109      * to the pool. If there is an existing idle thread available, the task will be handed to that
110      * thread to execute. If the specified maximum thread limit is reached, subsequent tasks will be
111      * queued and will execute as threads become available. If the maximum queue capacity is
112      * reached, subsequent tasks will be rejected.
113      *
114      * <p>Threads that have not been used for sixty seconds are terminated and removed from the pool.
115      * Thus, a pool that remains idle for long enough will not consume any resources.
116      *
117      * <p>By reusing threads when possible, this executor optimizes for reduced memory and thread
118      * resource overhead at the expense of execution time.
119      *
120      * <p>If you need an executor with faster execution time where increased memory and thread resource
121      * overhead is acceptable, consider using {@link #newBoundedFastThreadPool }.
122      *
123      * @param maximumPoolSize
124      *            the maximum number of threads to allow in the pool. Threads will terminate after
125      *            being idle for 60 seconds.
126      * @param maximumQueueSize
127      *            the capacity of the queue.
128      * @param threadPrefix
129      *            the name prefix for threads created by this executor.
130      * @return a new ExecutorService with the specified configuration.
131      */
132     public static ExecutorService newBoundedCachedThreadPool(int maximumPoolSize,
133             int maximumQueueSize, String threadPrefix, Class<?> loggerIdentity) {
134         return new CachedThreadPoolExecutor(maximumPoolSize, maximumQueueSize, threadPrefix, loggerIdentity);
135     }
136
137     /**
138      * Deprecated variant.
139      * @deprecated Please use {@link #newBoundedCachedThreadPool(int, int, String, Class)} instead.
140      */
141     @Deprecated
142     public static ExecutorService newBoundedCachedThreadPool(int maximumPoolSize,
143             int maximumQueueSize, String threadPrefix) {
144         return new CachedThreadPoolExecutor(maximumPoolSize, maximumQueueSize, threadPrefix, SpecialExecutors.class);
145     }
146
147     /**
148      * Creates an ExecutorService similar to {@link #newBoundedCachedThreadPool } except that it
149      * handles rejected tasks by running them in the same thread as the caller. Therefore if the
150      * queue is full, the caller submitting the task will be blocked until the task completes. In
151      * this manner, tasks are never rejected.
152      *
153      * @param maximumPoolSize
154      *            the maximum number of threads to allow in the pool. Threads will terminate after
155      *            being idle for 60 seconds.
156      * @param maximumQueueSize
157      *            the capacity of the queue.
158      * @param threadPrefix
159      *            the name prefix for threads created by this executor.
160      * @return a new ExecutorService with the specified configuration.
161      */
162     public static ExecutorService newBlockingBoundedCachedThreadPool(int maximumPoolSize,
163             int maximumQueueSize, String threadPrefix, Class<?> loggerIdentity) {
164
165         CachedThreadPoolExecutor executor = new CachedThreadPoolExecutor(maximumPoolSize, maximumQueueSize,
166                 threadPrefix, loggerIdentity);
167         executor.setRejectedExecutionHandler(CountingRejectedExecutionHandler.newCallerRunsPolicy());
168         return executor;
169     }
170
171     /**
172      * Deprecated variant.
173      * @deprecated Please use {@link #newBlockingBoundedCachedThreadPool(int, int, String, Class)} instead.
174      */
175     @Deprecated
176     public static ExecutorService newBlockingBoundedCachedThreadPool(int maximumPoolSize, int maximumQueueSize,
177             String threadPrefix) {
178         return newBlockingBoundedCachedThreadPool(maximumPoolSize, maximumQueueSize, threadPrefix,
179                 SpecialExecutors.class);
180     }
181
182     /**
183      * Creates an ExecutorService that uses a single worker thread operating off a bounded queue
184      * with the specified capacity. Tasks are guaranteed to execute sequentially, and no more than
185      * one task will be active at any given time. If the maximum queue capacity is reached,
186      * subsequent tasks will be rejected.
187      *
188      * @param maximumQueueSize
189      *            the capacity of the queue.
190      * @param threadPrefix
191      *            the name prefix for the thread created by this executor.
192      * @param loggerIdentity
193      *               the class to use as logger name for logging uncaught exceptions from the threads.
194      * @return a new ExecutorService with the specified configuration.
195      */
196     public static ExecutorService newBoundedSingleThreadExecutor(int maximumQueueSize,
197             String threadPrefix, Class<?> loggerIdentity) {
198         return new FastThreadPoolExecutor(1, maximumQueueSize, Long.MAX_VALUE, TimeUnit.SECONDS,
199                 threadPrefix, loggerIdentity);
200     }
201
202     /**
203      * Deprecated variant.
204      * @deprecated Please use {@link #newBoundedSingleThreadExecutor(int, String, Class)} instead.
205      */
206     @Deprecated
207     public static ExecutorService newBoundedSingleThreadExecutor(int maximumQueueSize, String threadPrefix) {
208         return newBoundedSingleThreadExecutor(maximumQueueSize, threadPrefix, SpecialExecutors.class);
209     }
210 }