1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import java.io.OutputStreamWriter;
22 import java.io.PrintStream;
23 import java.io.PrintWriter;
24 import java.lang.Thread.UncaughtExceptionHandler;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.nio.charset.StandardCharsets;
28 import java.util.concurrent.LinkedBlockingQueue;
29 import java.util.concurrent.ThreadFactory;
30 import java.util.concurrent.ThreadPoolExecutor;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.atomic.AtomicInteger;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.hbase.classification.InterfaceAudience;
37 import org.apache.hadoop.util.ReflectionUtils;
38 import org.apache.hadoop.util.StringUtils;
39
40
41
42
43 @InterfaceAudience.Private
44 public class Threads {
45 private static final Log LOG = LogFactory.getLog(Threads.class);
46 private static final AtomicInteger poolNumber = new AtomicInteger(1);
47
48 public static final UncaughtExceptionHandler LOGGING_EXCEPTION_HANDLER =
49 new UncaughtExceptionHandler() {
50 @Override
51 public void uncaughtException(Thread t, Throwable e) {
52 LOG.warn("Thread:" + t + " exited with Exception:"
53 + StringUtils.stringifyException(e));
54 }
55 };
56
57
58
59
60
61
62 public static Thread setDaemonThreadRunning(final Thread t) {
63 return setDaemonThreadRunning(t, t.getName());
64 }
65
66
67
68
69
70
71
72 public static Thread setDaemonThreadRunning(final Thread t,
73 final String name) {
74 return setDaemonThreadRunning(t, name, null);
75 }
76
77
78
79
80
81
82
83
84
85 public static Thread setDaemonThreadRunning(final Thread t,
86 final String name, final UncaughtExceptionHandler handler) {
87 t.setName(name);
88 if (handler != null) {
89 t.setUncaughtExceptionHandler(handler);
90 }
91 t.setDaemon(true);
92 t.start();
93 return t;
94 }
95
96
97
98
99
100 public static void shutdown(final Thread t) {
101 shutdown(t, 0);
102 }
103
104
105
106
107
108
109 public static void shutdown(final Thread t, final long joinwait) {
110 if (t == null) return;
111 while (t.isAlive()) {
112 try {
113 t.join(joinwait);
114 } catch (InterruptedException e) {
115 LOG.warn(t.getName() + "; joinwait=" + joinwait, e);
116 }
117 }
118 }
119
120
121
122
123
124
125
126 public static void threadDumpingIsAlive(final Thread t)
127 throws InterruptedException {
128 if (t == null) {
129 return;
130 }
131
132 while (t.isAlive()) {
133 t.join(60 * 1000);
134 if (t.isAlive()) {
135 printThreadInfo(System.out,
136 "Automatic Stack Trace every 60 seconds waiting on " +
137 t.getName());
138 }
139 }
140 }
141
142
143
144
145
146 public static void sleep(long millis) {
147 try {
148 Thread.sleep(millis);
149 } catch (InterruptedException e) {
150 e.printStackTrace();
151 Thread.currentThread().interrupt();
152 }
153 }
154
155
156
157
158
159
160 public static void sleepWithoutInterrupt(final long msToWait) {
161 long timeMillis = System.currentTimeMillis();
162 long endTime = timeMillis + msToWait;
163 boolean interrupted = false;
164 while (timeMillis < endTime) {
165 try {
166 Thread.sleep(endTime - timeMillis);
167 } catch (InterruptedException ex) {
168 interrupted = true;
169 }
170 timeMillis = System.currentTimeMillis();
171 }
172
173 if (interrupted) {
174 Thread.currentThread().interrupt();
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189 public static ThreadPoolExecutor getBoundedCachedThreadPool(
190 int maxCachedThread, long timeout, TimeUnit unit,
191 ThreadFactory threadFactory) {
192 ThreadPoolExecutor boundedCachedThreadPool =
193 new ThreadPoolExecutor(maxCachedThread, maxCachedThread, timeout,
194 unit, new LinkedBlockingQueue<Runnable>(), threadFactory);
195
196 boundedCachedThreadPool.allowCoreThreadTimeOut(true);
197 return boundedCachedThreadPool;
198 }
199
200
201
202
203
204
205
206
207 public static ThreadFactory getNamedThreadFactory(final String prefix) {
208 SecurityManager s = System.getSecurityManager();
209 final ThreadGroup threadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread()
210 .getThreadGroup();
211
212 return new ThreadFactory() {
213 final AtomicInteger threadNumber = new AtomicInteger(1);
214 private final int poolNumber = Threads.poolNumber.getAndIncrement();
215 final ThreadGroup group = threadGroup;
216
217 @Override
218 public Thread newThread(Runnable r) {
219 final String name = prefix + "-pool" + poolNumber + "-t" + threadNumber.getAndIncrement();
220 return new Thread(group, r, name);
221 }
222 };
223 }
224
225
226
227
228
229 public static ThreadFactory newDaemonThreadFactory(final String prefix) {
230 return newDaemonThreadFactory(prefix, null);
231 }
232
233
234
235
236
237
238
239
240 public static ThreadFactory newDaemonThreadFactory(final String prefix,
241 final UncaughtExceptionHandler handler) {
242 final ThreadFactory namedFactory = getNamedThreadFactory(prefix);
243 return new ThreadFactory() {
244 @Override
245 public Thread newThread(Runnable r) {
246 Thread t = namedFactory.newThread(r);
247 if (handler != null) {
248 t.setUncaughtExceptionHandler(handler);
249 } else {
250 t.setUncaughtExceptionHandler(LOGGING_EXCEPTION_HANDLER);
251 }
252 if (!t.isDaemon()) {
253 t.setDaemon(true);
254 }
255 if (t.getPriority() != Thread.NORM_PRIORITY) {
256 t.setPriority(Thread.NORM_PRIORITY);
257 }
258 return t;
259 }
260
261 };
262 }
263
264
265
266
267 public static void setLoggingUncaughtExceptionHandler(Thread t) {
268 t.setUncaughtExceptionHandler(LOGGING_EXCEPTION_HANDLER);
269 }
270
271 private static Method PRINT_THREAD_INFO_METHOD = null;
272 private static boolean PRINT_THREAD_INFO_METHOD_WITH_PRINTSTREAM = true;
273
274
275
276
277
278
279
280 public static synchronized void printThreadInfo(PrintStream stream, String title) {
281 if (PRINT_THREAD_INFO_METHOD == null) {
282 try {
283
284 PRINT_THREAD_INFO_METHOD = ReflectionUtils.class.getMethod("printThreadInfo",
285 PrintStream.class, String.class);
286 } catch (NoSuchMethodException e) {
287
288 PRINT_THREAD_INFO_METHOD_WITH_PRINTSTREAM = false;
289 try {
290 PRINT_THREAD_INFO_METHOD = ReflectionUtils.class.getMethod("printThreadInfo",
291 PrintWriter.class, String.class);
292 } catch (NoSuchMethodException e1) {
293 throw new RuntimeException("Cannot find method. Check hadoop jars linked", e1);
294 }
295 }
296 PRINT_THREAD_INFO_METHOD.setAccessible(true);
297 }
298
299 try {
300 if (PRINT_THREAD_INFO_METHOD_WITH_PRINTSTREAM) {
301 PRINT_THREAD_INFO_METHOD.invoke(null, stream, title);
302 } else {
303 PRINT_THREAD_INFO_METHOD.invoke(null,
304 new PrintWriter(new OutputStreamWriter(stream, StandardCharsets.UTF_8)), title);
305 }
306 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
307 throw new RuntimeException(e.getCause());
308 }
309 }
310 }