001/*
002 * Copyright 2002-2014 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 *      https://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
017package org.springframework.util;
018
019import java.io.Serializable;
020import java.util.concurrent.atomic.AtomicInteger;
021
022/**
023 * Simple customizable helper class for creating new {@link Thread} instances.
024 * Provides various bean properties: thread name prefix, thread priority, etc.
025 *
026 * <p>Serves as base class for thread factories such as
027 * {@link org.springframework.scheduling.concurrent.CustomizableThreadFactory}.
028 *
029 * @author Juergen Hoeller
030 * @since 2.0.3
031 * @see org.springframework.scheduling.concurrent.CustomizableThreadFactory
032 */
033@SuppressWarnings("serial")
034public class CustomizableThreadCreator implements Serializable {
035
036        private String threadNamePrefix;
037
038        private int threadPriority = Thread.NORM_PRIORITY;
039
040        private boolean daemon = false;
041
042        private ThreadGroup threadGroup;
043
044        private final AtomicInteger threadCount = new AtomicInteger(0);
045
046
047        /**
048         * Create a new CustomizableThreadCreator with default thread name prefix.
049         */
050        public CustomizableThreadCreator() {
051                this.threadNamePrefix = getDefaultThreadNamePrefix();
052        }
053
054        /**
055         * Create a new CustomizableThreadCreator with the given thread name prefix.
056         * @param threadNamePrefix the prefix to use for the names of newly created threads
057         */
058        public CustomizableThreadCreator(String threadNamePrefix) {
059                this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
060        }
061
062
063        /**
064         * Specify the prefix to use for the names of newly created threads.
065         * Default is "SimpleAsyncTaskExecutor-".
066         */
067        public void setThreadNamePrefix(String threadNamePrefix) {
068                this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
069        }
070
071        /**
072         * Return the thread name prefix to use for the names of newly
073         * created threads.
074         */
075        public String getThreadNamePrefix() {
076                return this.threadNamePrefix;
077        }
078
079        /**
080         * Set the priority of the threads that this factory creates.
081         * Default is 5.
082         * @see java.lang.Thread#NORM_PRIORITY
083         */
084        public void setThreadPriority(int threadPriority) {
085                this.threadPriority = threadPriority;
086        }
087
088        /**
089         * Return the priority of the threads that this factory creates.
090         */
091        public int getThreadPriority() {
092                return this.threadPriority;
093        }
094
095        /**
096         * Set whether this factory is supposed to create daemon threads,
097         * just executing as long as the application itself is running.
098         * <p>Default is "false": Concrete factories usually support explicit cancelling.
099         * Hence, if the application shuts down, Runnables will by default finish their
100         * execution.
101         * <p>Specify "true" for eager shutdown of threads which still actively execute
102         * a {@link Runnable} at the time that the application itself shuts down.
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} 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 new {@link Thread}.
143         * <p>The default implementation creates a new Thread for the given
144         * {@link 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 {@link Thread}.
157         * <p>The default implementation returns the specified thread name prefix
158         * with an increasing thread count appended: e.g. "SimpleAsyncTaskExecutor-0".
159         * @see #getThreadNamePrefix()
160         */
161        protected String nextThreadName() {
162                return getThreadNamePrefix() + this.threadCount.incrementAndGet();
163        }
164
165        /**
166         * Build the default thread name prefix for this factory.
167         * @return the default thread name prefix (never {@code null})
168         */
169        protected String getDefaultThreadNamePrefix() {
170                return ClassUtils.getShortName(getClass()) + "-";
171        }
172
173}