1 /*
2 * Copyright 2002-2009 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.util;
18
19 import java.io.Serializable;
20
21 /**
22 * Simple customizable helper class for creating threads. Provides various
23 * bean properties, such as thread name prefix, thread priority, etc.
24 *
25 * <p>Serves as base class for thread factories such as
26 * {@link org.springframework.scheduling.concurrent.CustomizableThreadFactory}.
27 *
28 * @author Juergen Hoeller
29 * @since 2.0.3
30 * @see org.springframework.scheduling.concurrent.CustomizableThreadFactory
31 */
32 public class CustomizableThreadCreator implements Serializable {
33
34 private String threadNamePrefix;
35
36 private int threadPriority = Thread.NORM_PRIORITY;
37
38 private boolean daemon = false;
39
40 private ThreadGroup threadGroup;
41
42 private int threadCount = 0;
43
44 private final Object threadCountMonitor = new SerializableMonitor();
45
46
47 /**
48 * Create a new CustomizableThreadCreator with default thread name prefix.
49 */
50 public CustomizableThreadCreator() {
51 this.threadNamePrefix = getDefaultThreadNamePrefix();
52 }
53
54 /**
55 * Create a new CustomizableThreadCreator with the given thread name prefix.
56 * @param threadNamePrefix the prefix to use for the names of newly created threads
57 */
58 public CustomizableThreadCreator(String threadNamePrefix) {
59 this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
60 }
61
62
63 /**
64 * Specify the prefix to use for the names of newly created threads.
65 * Default is "SimpleAsyncTaskExecutor-".
66 */
67 public void setThreadNamePrefix(String threadNamePrefix) {
68 this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
69 }
70
71 /**
72 * Return the thread name prefix to use for the names of newly
73 * created threads.
74 */
75 public String getThreadNamePrefix() {
76 return this.threadNamePrefix;
77 }
78
79 /**
80 * Set the priority of the threads that this factory creates.
81 * Default is 5.
82 * @see java.lang.Thread#NORM_PRIORITY
83 */
84 public void setThreadPriority(int threadPriority) {
85 this.threadPriority = threadPriority;
86 }
87
88 /**
89 * Return the priority of the threads that this factory creates.
90 */
91 public int getThreadPriority() {
92 return this.threadPriority;
93 }
94
95 /**
96 * Set whether this factory is supposed to create daemon threads,
97 * just executing as long as the application itself is running.
98 * <p>Default is "false": Concrete factories usually support explicit
99 * cancelling. Hence, if the application shuts down, Runnables will
100 * by default finish their execution.
101 * <p>Specify "true" for eager shutdown of threads which still
102 * actively execute a Runnable.
103 * @see java.lang.Thread#setDaemon
104 */
105 public void setDaemon(boolean daemon) {
106 this.daemon = daemon;
107 }
108
109 /**
110 * Return whether this factory should create daemon threads.
111 */
112 public boolean isDaemon() {
113 return this.daemon;
114 }
115
116 /**
117 * Specify the name of the thread group that threads should be created in.
118 * @see #setThreadGroup
119 */
120 public void setThreadGroupName(String name) {
121 this.threadGroup = new ThreadGroup(name);
122 }
123
124 /**
125 * Specify the thread group that threads should be created in.
126 * @see #setThreadGroupName
127 */
128 public void setThreadGroup(ThreadGroup threadGroup) {
129 this.threadGroup = threadGroup;
130 }
131
132 /**
133 * Return the thread group that threads should be created in
134 * (or <code>null</code>) for the default group.
135 */
136 public ThreadGroup getThreadGroup() {
137 return this.threadGroup;
138 }
139
140
141 /**
142 * Template method for the creation of a Thread.
143 * <p>Default implementation creates a new Thread for the given
144 * Runnable, applying an appropriate thread name.
145 * @param runnable the Runnable to execute
146 * @see #nextThreadName()
147 */
148 public Thread createThread(Runnable runnable) {
149 Thread thread = new Thread(getThreadGroup(), runnable, nextThreadName());
150 thread.setPriority(getThreadPriority());
151 thread.setDaemon(isDaemon());
152 return thread;
153 }
154
155 /**
156 * Return the thread name to use for a newly created thread.
157 * <p>Default implementation returns the specified thread name prefix
158 * with an increasing thread count appended: for example,
159 * "SimpleAsyncTaskExecutor-0".
160 * @see #getThreadNamePrefix()
161 */
162 protected String nextThreadName() {
163 int threadNumber = 0;
164 synchronized (this.threadCountMonitor) {
165 this.threadCount++;
166 threadNumber = this.threadCount;
167 }
168 return getThreadNamePrefix() + threadNumber;
169 }
170
171 /**
172 * Build the default thread name prefix for this factory.
173 * @return the default thread name prefix (never <code>null</code>)
174 */
175 protected String getDefaultThreadNamePrefix() {
176 return ClassUtils.getShortName(getClass()) + "-";
177 }
178
179
180 /**
181 * Empty class used for a serializable monitor object.
182 */
183 private static class SerializableMonitor implements Serializable {
184 }
185
186 }