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}