b2054936471afe9299bb3a334b476c7c0d0caf83
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / concurrent / FastThreadPoolExecutor.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 com.google.common.base.MoreObjects;
12 import com.google.common.base.MoreObjects.ToStringHelper;
13 import java.util.concurrent.ThreadPoolExecutor;
14 import java.util.concurrent.TimeUnit;
15 import org.slf4j.LoggerFactory;
16
17 /**
18  * A ThreadPoolExecutor with a specified bounded queue capacity that favors creating new threads
19  * over queuing, as the former is faster.
20  *
21  * <p>See {@link SpecialExecutors#newBoundedFastThreadPool} for more details.
22  *
23  * @author Thomas Pantelis
24  */
25 public class FastThreadPoolExecutor extends ThreadPoolExecutor {
26
27     private static final long DEFAULT_IDLE_TIMEOUT_IN_SEC = 15L;
28
29     private final String threadPrefix;
30     private final int maximumQueueSize;
31
32     /**
33      * Constructs a FastThreadPoolExecutor instance.
34      *
35      * @param maximumPoolSize
36      *            the maximum number of threads to allow in the pool. Threads will terminate after
37      *            being idle for 15 seconds.
38      * @param maximumQueueSize
39      *            the capacity of the queue.
40      * @param threadPrefix
41      *            the name prefix for threads created by this executor.
42      * @param loggerIdentity
43      *               the class to use as logger name for logging uncaught exceptions from the threads.
44      */
45     public FastThreadPoolExecutor(final int maximumPoolSize, final int maximumQueueSize, final String threadPrefix,
46             Class<?> loggerIdentity) {
47         this(maximumPoolSize, maximumQueueSize, DEFAULT_IDLE_TIMEOUT_IN_SEC, TimeUnit.SECONDS,
48               threadPrefix, loggerIdentity);
49     }
50
51     /**
52      * Constructor.
53      *
54      * @deprecated Please use
55      *             {@link #FastThreadPoolExecutor(int, int, String, Class)}
56      *             instead.
57      */
58     @Deprecated
59     public FastThreadPoolExecutor(final int maximumPoolSize, final int maximumQueueSize, final String threadPrefix) {
60         this(maximumPoolSize, maximumQueueSize, DEFAULT_IDLE_TIMEOUT_IN_SEC, TimeUnit.SECONDS,
61               threadPrefix);
62     }
63
64     /**
65      * Constructor.
66      *
67      * @deprecated Please use
68      *             {@link #FastThreadPoolExecutor(int, int, long, TimeUnit, String, Class)}
69      *             instead.
70      */
71     @Deprecated
72     public FastThreadPoolExecutor(final int maximumPoolSize, final int maximumQueueSize, final long keepAliveTime,
73             final TimeUnit unit, final String threadPrefix) {
74         this(maximumPoolSize, maximumQueueSize, keepAliveTime, unit, threadPrefix, FastThreadPoolExecutor.class);
75     }
76
77     /**
78      * Constructs a FastThreadPoolExecutor instance.
79      *
80      * @param maximumPoolSize
81      *            the maximum number of threads to allow in the pool.
82      * @param maximumQueueSize
83      *            the capacity of the queue.
84      * @param keepAliveTime
85      *            the maximum time that idle threads will wait for new tasks before terminating.
86      * @param unit
87      *            the time unit for the keepAliveTime argument
88      * @param threadPrefix
89      *            the name prefix for threads created by this executor.
90      * @param loggerIdentity
91      *               the class to use as logger name for logging uncaught exceptions from the threads.
92      */
93     @SuppressWarnings("checkstyle:LoggerFactoryClassParameter") // due to loggerIdentity argument usage
94     public FastThreadPoolExecutor(final int maximumPoolSize, final int maximumQueueSize, final long keepAliveTime,
95             final TimeUnit unit, final String threadPrefix, Class<?> loggerIdentity) {
96         // We use all core threads (the first 2 parameters below equal) so, when a task is submitted,
97         // if the thread limit hasn't been reached, a new thread will be spawned to execute
98         // the task even if there is an existing idle thread in the pool. This is faster than
99         // handing the task to an existing idle thread via the queue. Once the thread limit is
100         // reached, subsequent tasks will be queued. If the queue is full, tasks will be rejected.
101
102         super(maximumPoolSize, maximumPoolSize, keepAliveTime, unit,
103                 new TrackingLinkedBlockingQueue<>(maximumQueueSize));
104
105         this.threadPrefix = threadPrefix;
106         this.maximumQueueSize = maximumQueueSize;
107
108         setThreadFactory(ThreadFactoryProvider.builder().namePrefix(threadPrefix)
109                 .logger(LoggerFactory.getLogger(loggerIdentity)).build().get());
110
111         if (keepAliveTime > 0) {
112             // Need to specifically configure core threads to timeout.
113             allowCoreThreadTimeOut(true);
114         }
115
116         setRejectedExecutionHandler(CountingRejectedExecutionHandler.newAbortPolicy());
117     }
118
119     public long getLargestQueueSize() {
120         return ((TrackingLinkedBlockingQueue<?>)getQueue()).getLargestQueueSize();
121     }
122
123     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
124         return toStringHelper;
125     }
126
127     @Override
128     public final String toString() {
129         return addToStringAttributes(MoreObjects.toStringHelper(this)
130                 .add("Thread Prefix", threadPrefix)
131                 .add("Current Thread Pool Size", getPoolSize())
132                 .add("Largest Thread Pool Size", getLargestPoolSize())
133                 .add("Max Thread Pool Size", getMaximumPoolSize())
134                 .add("Current Queue Size", getQueue().size())
135                 .add("Largest Queue Size", getLargestQueueSize())
136                 .add("Max Queue Size", maximumQueueSize)
137                 .add("Active Thread Count", getActiveCount())
138                 .add("Completed Task Count", getCompletedTaskCount())
139                 .add("Total Task Count", getTaskCount())).toString();
140     }
141 }