001/* 002 * Copyright 2012-2018 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 017package org.springframework.boot.task; 018 019import java.util.Arrays; 020import java.util.Collections; 021import java.util.LinkedHashSet; 022import java.util.Set; 023 024import org.springframework.boot.context.properties.PropertyMapper; 025import org.springframework.scheduling.TaskScheduler; 026import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 027import org.springframework.util.Assert; 028import org.springframework.util.CollectionUtils; 029 030/** 031 * Builder that can be used to configure and create a {@link TaskScheduler}. Provides 032 * convenience methods to set common {@link ThreadPoolTaskScheduler} settings. For 033 * advanced configuration, consider using {@link TaskSchedulerCustomizer}. 034 * <p> 035 * In a typical auto-configured Spring Boot application this builder is available as a 036 * bean and can be injected whenever a {@link TaskScheduler} is needed. 037 * 038 * @author Stephane Nicoll 039 * @since 2.1.0 040 */ 041public class TaskSchedulerBuilder { 042 043 private final Integer poolSize; 044 045 private final String threadNamePrefix; 046 047 private final Set<TaskSchedulerCustomizer> customizers; 048 049 public TaskSchedulerBuilder() { 050 this.poolSize = null; 051 this.threadNamePrefix = null; 052 this.customizers = null; 053 } 054 055 public TaskSchedulerBuilder(Integer poolSize, String threadNamePrefix, 056 Set<TaskSchedulerCustomizer> taskSchedulerCustomizers) { 057 this.poolSize = poolSize; 058 this.threadNamePrefix = threadNamePrefix; 059 this.customizers = taskSchedulerCustomizers; 060 } 061 062 /** 063 * Set the maximum allowed number of threads. 064 * @param poolSize the pool size to set 065 * @return a new builder instance 066 */ 067 public TaskSchedulerBuilder poolSize(int poolSize) { 068 return new TaskSchedulerBuilder(poolSize, this.threadNamePrefix, 069 this.customizers); 070 } 071 072 /** 073 * Set the prefix to use for the names of newly created threads. 074 * @param threadNamePrefix the thread name prefix to set 075 * @return a new builder instance 076 */ 077 public TaskSchedulerBuilder threadNamePrefix(String threadNamePrefix) { 078 return new TaskSchedulerBuilder(this.poolSize, threadNamePrefix, 079 this.customizers); 080 } 081 082 /** 083 * Set the {@link TaskSchedulerCustomizer TaskSchedulerCustomizers} that should be 084 * applied to the {@link ThreadPoolTaskScheduler}. Customizers are applied in the 085 * order that they were added after builder configuration has been applied. Setting 086 * this value will replace any previously configured customizers. 087 * @param customizers the customizers to set 088 * @return a new builder instance 089 * @see #additionalCustomizers(TaskSchedulerCustomizer...) 090 */ 091 public TaskSchedulerBuilder customizers(TaskSchedulerCustomizer... customizers) { 092 Assert.notNull(customizers, "Customizers must not be null"); 093 return customizers(Arrays.asList(customizers)); 094 } 095 096 /** 097 * Set the {@link TaskSchedulerCustomizer taskSchedulerCustomizers} that should be 098 * applied to the {@link ThreadPoolTaskScheduler}. Customizers are applied in the 099 * order that they were added after builder configuration has been applied. Setting 100 * this value will replace any previously configured customizers. 101 * @param customizers the customizers to set 102 * @return a new builder instance 103 * @see #additionalCustomizers(TaskSchedulerCustomizer...) 104 */ 105 public TaskSchedulerBuilder customizers( 106 Iterable<TaskSchedulerCustomizer> customizers) { 107 Assert.notNull(customizers, "Customizers must not be null"); 108 return new TaskSchedulerBuilder(this.poolSize, this.threadNamePrefix, 109 append(null, customizers)); 110 } 111 112 /** 113 * Add {@link TaskSchedulerCustomizer taskSchedulerCustomizers} that should be applied 114 * to the {@link ThreadPoolTaskScheduler}. Customizers are applied in the order that 115 * they were added after builder configuration has been applied. 116 * @param customizers the customizers to add 117 * @return a new builder instance 118 * @see #customizers(TaskSchedulerCustomizer...) 119 */ 120 public TaskSchedulerBuilder additionalCustomizers( 121 TaskSchedulerCustomizer... customizers) { 122 Assert.notNull(customizers, "Customizers must not be null"); 123 return additionalCustomizers(Arrays.asList(customizers)); 124 } 125 126 /** 127 * Add {@link TaskSchedulerCustomizer taskSchedulerCustomizers} that should be applied 128 * to the {@link ThreadPoolTaskScheduler}. Customizers are applied in the order that 129 * they were added after builder configuration has been applied. 130 * @param customizers the customizers to add 131 * @return a new builder instance 132 * @see #customizers(TaskSchedulerCustomizer...) 133 */ 134 public TaskSchedulerBuilder additionalCustomizers( 135 Iterable<TaskSchedulerCustomizer> customizers) { 136 Assert.notNull(customizers, "Customizers must not be null"); 137 return new TaskSchedulerBuilder(this.poolSize, this.threadNamePrefix, 138 append(this.customizers, customizers)); 139 } 140 141 /** 142 * Build a new {@link ThreadPoolTaskScheduler} instance and configure it using this 143 * builder. 144 * @return a configured {@link ThreadPoolTaskScheduler} instance. 145 * @see #configure(ThreadPoolTaskScheduler) 146 */ 147 public ThreadPoolTaskScheduler build() { 148 return configure(new ThreadPoolTaskScheduler()); 149 } 150 151 /** 152 * Configure the provided {@link ThreadPoolTaskScheduler} instance using this builder. 153 * @param <T> the type of task scheduler 154 * @param taskScheduler the {@link ThreadPoolTaskScheduler} to configure 155 * @return the task scheduler instance 156 * @see #build() 157 */ 158 public <T extends ThreadPoolTaskScheduler> T configure(T taskScheduler) { 159 PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); 160 map.from(this.poolSize).to(taskScheduler::setPoolSize); 161 map.from(this.threadNamePrefix).to(taskScheduler::setThreadNamePrefix); 162 if (!CollectionUtils.isEmpty(this.customizers)) { 163 this.customizers.forEach((customizer) -> customizer.customize(taskScheduler)); 164 } 165 return taskScheduler; 166 } 167 168 private <T> Set<T> append(Set<T> set, Iterable<? extends T> additions) { 169 Set<T> result = new LinkedHashSet<>((set != null) ? set : Collections.emptySet()); 170 additions.forEach(result::add); 171 return Collections.unmodifiableSet(result); 172 } 173 174}