001/*
002 * Copyright 2002-2017 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
022import org.springframework.lang.Nullable;
023
024/**
025 * Simple customizable helper class for creating new {@link Thread} instances.
026 * Provides various bean properties: thread name prefix, thread priority, etc.
027 *
028 * <p>Serves as base class for thread factories such as
029 * {@link org.springframework.scheduling.concurrent.CustomizableThreadFactory}.
030 *
031 * @author Juergen Hoeller
032 * @since 2.0.3
033 * @see org.springframework.scheduling.concurrent.CustomizableThreadFactory
034 */
035@SuppressWarnings("serial")
036public class CustomizableThreadCreator implements Serializable {
037
038        private String threadNamePrefix;
039
040        private int threadPriority = Thread.NORM_PRIORITY;
041
042        private boolean daemon = false;
043
044        @Nullable
045        private ThreadGroup threadGroup;
046
047        private final AtomicInteger threadCount = new AtomicInteger(0);
048
049
050        /**
051         * Create a new CustomizableThreadCreator with default thread name prefix.
052         */
053        public CustomizableThreadCreator() {
054                this.threadNamePrefix = getDefaultThreadNamePrefix();
055        }
056
057        /**
058         * Create a new CustomizableThreadCreator with the given thread name prefix.
059         * @param threadNamePrefix the prefix to use for the names of newly created threads
060         */
061        public CustomizableThreadCreator(@Nullable String threadNamePrefix) {
062                this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
063        }
064
065
066        /**
067         * Specify the prefix to use for the names of newly created threads.
068         * Default is "SimpleAsyncTaskExecutor-".
069         */
070        public void setThreadNamePrefix(@Nullable String threadNamePrefix) {
071                this.threadNamePrefix = (threadNamePrefix != null ? threadNamePrefix : getDefaultThreadNamePrefix());
072        }
073
074        /**
075         * Return the thread name prefix to use for the names of newly
076         * created threads.
077         */
078        public String getThreadNamePrefix() {
079                return this.threadNamePrefix;
080        }
081
082        /**
083         * Set the priority of the threads that this factory creates.
084         * Default is 5.
085         * @see java.lang.Thread#NORM_PRIORITY
086         */
087        public void setThreadPriority(int threadPriority) {
088                this.threadPriority = threadPriority;
089        }
090
091        /**
092         * Return the priority of the threads that this factory creates.
093         */
094        public int getThreadPriority() {
095                return this.threadPriority;
096        }
097
098        /**
099         * Set whether this factory is supposed to create daemon threads,
100         * just executing as long as the application itself is running.
101         * <p>Default is "false": Concrete factories usually support explicit cancelling.
102         * Hence, if the application shuts down, Runnables will by default finish their
103         * execution.
104         * <p>Specify "true" for eager shutdown of threads which still actively execute
105         * a {@link Runnable} at the time that the application itself shuts down.
106         * @see java.lang.Thread#setDaemon
107         */
108        public void setDaemon(boolean daemon) {
109                this.daemon = daemon;
110        }
111
112        /**
113         * Return whether this factory should create daemon threads.
114         */
115        public boolean isDaemon() {
116                return this.daemon;
117        }
118
119        /**
120         * Specify the name of the thread group that threads should be created in.
121         * @see #setThreadGroup
122         */
123        public void setThreadGroupName(String name) {
124                this.threadGroup = new ThreadGroup(name);
125        }
126
127        /**
128         * Specify the thread group that threads should be created in.
129         * @see #setThreadGroupName
130         */
131        public void setThreadGroup(@Nullable ThreadGroup threadGroup) {
132                this.threadGroup = threadGroup;
133        }
134
135        /**
136         * Return the thread group that threads should be created in
137         * (or {@code null} for the default group).
138         */
139        @Nullable
140        public ThreadGroup getThreadGroup() {
141                return this.threadGroup;
142        }
143
144
145        /**
146         * Template method for the creation of a new {@link Thread}.
147         * <p>The default implementation creates a new Thread for the given
148         * {@link Runnable}, applying an appropriate thread name.
149         * @param runnable the Runnable to execute
150         * @see #nextThreadName()
151         */
152        public Thread createThread(Runnable runnable) {
153                Thread thread = new Thread(getThreadGroup(), runnable, nextThreadName());
154                thread.setPriority(getThreadPriority());
155                thread.setDaemon(isDaemon());
156                return thread;
157        }
158
159        /**
160         * Return the thread name to use for a newly created {@link Thread}.
161         * <p>The default implementation returns the specified thread name prefix
162         * with an increasing thread count appended: e.g. "SimpleAsyncTaskExecutor-0".
163         * @see #getThreadNamePrefix()
164         */
165        protected String nextThreadName() {
166                return getThreadNamePrefix() + this.threadCount.incrementAndGet();
167        }
168
169        /**
170         * Build the default thread name prefix for this factory.
171         * @return the default thread name prefix (never {@code null})
172         */
173        protected String getDefaultThreadNamePrefix() {
174                return ClassUtils.getShortName(getClass()) + "-";
175        }
176
177}