001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.util;
018:
019: /**
020: * Simple customizable helper class for creating threads. Provides various
021: * bean properties, such as thread name prefix, thread priority, etc.
022: *
023: * <p>Serves as base class for thread factories such as
024: * {@link org.springframework.scheduling.concurrent.CustomizableThreadFactory}.
025: *
026: * @author Juergen Hoeller
027: * @since 2.0.3
028: * @see org.springframework.scheduling.concurrent.CustomizableThreadFactory
029: */
030: public class CustomizableThreadCreator {
031:
032: private final Object monitor = new Object();
033:
034: private String threadNamePrefix;
035:
036: private int threadPriority = Thread.NORM_PRIORITY;
037:
038: private boolean daemon = false;
039:
040: private ThreadGroup threadGroup;
041:
042: private int threadCount = 0;
043:
044: /**
045: * Create a new CustomizableThreadCreator with default thread name prefix.
046: */
047: public CustomizableThreadCreator() {
048: this (null);
049: }
050:
051: /**
052: * Create a new CustomizableThreadCreator with the given thread name prefix.
053: * @param threadNamePrefix the prefix to use for the names of newly created threads
054: */
055: public CustomizableThreadCreator(String threadNamePrefix) {
056: setThreadNamePrefix(threadNamePrefix);
057: }
058:
059: /**
060: * Specify the prefix to use for the names of newly created threads.
061: * Default is "SimpleAsyncTaskExecutor-".
062: */
063: public void setThreadNamePrefix(String threadNamePrefix) {
064: this .threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix
065: : getDefaultThreadNamePrefix());
066: }
067:
068: /**
069: * Return the thread name prefix to use for the names of newly
070: * created threads.
071: */
072: public String getThreadNamePrefix() {
073: return this .threadNamePrefix;
074: }
075:
076: /**
077: * Set the priority of the threads that this factory creates.
078: * Default is 5.
079: * @see java.lang.Thread#NORM_PRIORITY
080: */
081: public void setThreadPriority(int threadPriority) {
082: this .threadPriority = threadPriority;
083: }
084:
085: /**
086: * Return the priority of the threads that this factory creates.
087: */
088: public int getThreadPriority() {
089: return this .threadPriority;
090: }
091:
092: /**
093: * Set whether this factory is supposed to create daemon threads,
094: * just executing as long as the application itself is running.
095: * <p>Default is "false": Concrete factories usually support explicit
096: * cancelling. Hence, if the application shuts down, Runnables will
097: * by default finish their execution.
098: * <p>Specify "true" for eager shutdown of threads which still
099: * actively execute a Runnable.
100: * @see java.lang.Thread#setDaemon
101: */
102: public void setDaemon(boolean daemon) {
103: this .daemon = daemon;
104: }
105:
106: /**
107: * Return whether this factory should create daemon threads.
108: */
109: public boolean isDaemon() {
110: return this .daemon;
111: }
112:
113: /**
114: * Specify the name of the thread group that threads should be created in.
115: * @see #setThreadGroup
116: */
117: public void setThreadGroupName(String name) {
118: this .threadGroup = new ThreadGroup(name);
119: }
120:
121: /**
122: * Specify the thread group that threads should be created in.
123: * @see #setThreadGroupName
124: */
125: public void setThreadGroup(ThreadGroup threadGroup) {
126: this .threadGroup = threadGroup;
127: }
128:
129: /**
130: * Return the thread group that threads should be created in
131: * (or <code>null</code>) for the default group.
132: */
133: public ThreadGroup getThreadGroup() {
134: return this .threadGroup;
135: }
136:
137: /**
138: * Template method for the creation of a Thread.
139: * <p>Default implementation creates a new Thread for the given
140: * Runnable, applying an appropriate thread name.
141: * @param runnable the Runnable to execute
142: * @see #nextThreadName()
143: */
144: public Thread createThread(Runnable runnable) {
145: Thread thread = new Thread(getThreadGroup(), runnable,
146: nextThreadName());
147: thread.setPriority(getThreadPriority());
148: thread.setDaemon(isDaemon());
149: return thread;
150: }
151:
152: /**
153: * Return the thread name to use for a newly created thread.
154: * <p>Default implementation returns the specified thread name prefix
155: * with an increasing thread count appended: for example,
156: * "SimpleAsyncTaskExecutor-0".
157: * @see #getThreadNamePrefix()
158: */
159: protected String nextThreadName() {
160: int threadNumber = 0;
161: synchronized (this .monitor) {
162: this .threadCount++;
163: threadNumber = this .threadCount;
164: }
165: return getThreadNamePrefix() + threadNumber;
166: }
167:
168: /**
169: * Build the default thread name prefix for this factory.
170: * @return the default thread name prefix (never <code>null</code>)
171: */
172: protected String getDefaultThreadNamePrefix() {
173: return ClassUtils.getShortName(getClass()) + "-";
174: }
175:
176: }
|