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}