4040 * bean and can be injected whenever a {@link TaskExecutor} is needed. 
4141 * 
4242 * @author Stephane Nicoll 
43+  * @author Filip Hrisafov 
4344 * @since 2.1.0 
4445 */ 
4546public  class  TaskExecutorBuilder  {
@@ -56,6 +57,10 @@ public class TaskExecutorBuilder {
5657
5758	private  final  String  threadNamePrefix ;
5859
60+ 	private  final  Duration  awaitTermination ;
61+ 
62+ 	private  final  Boolean  waitForTasksToCompleteOnShutdown ;
63+ 
5964	private  final  TaskDecorator  taskDecorator ;
6065
6166	private  final  Set <TaskExecutorCustomizer > customizers ;
@@ -67,20 +72,25 @@ public TaskExecutorBuilder() {
6772		this .allowCoreThreadTimeOut  = null ;
6873		this .keepAlive  = null ;
6974		this .threadNamePrefix  = null ;
75+ 		this .awaitTermination  = null ;
76+ 		this .waitForTasksToCompleteOnShutdown  = null ;
7077		this .taskDecorator  = null ;
7178		this .customizers  = null ;
7279	}
7380
7481	private  TaskExecutorBuilder (Integer  queueCapacity , Integer  corePoolSize ,
7582			Integer  maxPoolSize , Boolean  allowCoreThreadTimeOut , Duration  keepAlive ,
76- 			String  threadNamePrefix , TaskDecorator  taskDecorator ,
83+ 			String  threadNamePrefix , Duration  awaitTermination ,
84+ 			Boolean  waitForTasksToCompleteOnShutdown , TaskDecorator  taskDecorator ,
7785			Set <TaskExecutorCustomizer > customizers ) {
7886		this .queueCapacity  = queueCapacity ;
7987		this .corePoolSize  = corePoolSize ;
8088		this .maxPoolSize  = maxPoolSize ;
8189		this .allowCoreThreadTimeOut  = allowCoreThreadTimeOut ;
8290		this .keepAlive  = keepAlive ;
8391		this .threadNamePrefix  = threadNamePrefix ;
92+ 		this .awaitTermination  = awaitTermination ;
93+ 		this .waitForTasksToCompleteOnShutdown  = waitForTasksToCompleteOnShutdown ;
8494		this .taskDecorator  = taskDecorator ;
8595		this .customizers  = customizers ;
8696	}
@@ -94,6 +104,7 @@ private TaskExecutorBuilder(Integer queueCapacity, Integer corePoolSize,
94104	public  TaskExecutorBuilder  queueCapacity (int  queueCapacity ) {
95105		return  new  TaskExecutorBuilder (queueCapacity , this .corePoolSize , this .maxPoolSize ,
96106				this .allowCoreThreadTimeOut , this .keepAlive , this .threadNamePrefix ,
107+ 				this .awaitTermination , this .waitForTasksToCompleteOnShutdown ,
97108				this .taskDecorator , this .customizers );
98109	}
99110
@@ -109,6 +120,7 @@ public TaskExecutorBuilder queueCapacity(int queueCapacity) {
109120	public  TaskExecutorBuilder  corePoolSize (int  corePoolSize ) {
110121		return  new  TaskExecutorBuilder (this .queueCapacity , corePoolSize , this .maxPoolSize ,
111122				this .allowCoreThreadTimeOut , this .keepAlive , this .threadNamePrefix ,
123+ 				this .awaitTermination , this .waitForTasksToCompleteOnShutdown ,
112124				this .taskDecorator , this .customizers );
113125	}
114126
@@ -124,6 +136,7 @@ public TaskExecutorBuilder corePoolSize(int corePoolSize) {
124136	public  TaskExecutorBuilder  maxPoolSize (int  maxPoolSize ) {
125137		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize , maxPoolSize ,
126138				this .allowCoreThreadTimeOut , this .keepAlive , this .threadNamePrefix ,
139+ 				this .awaitTermination , this .waitForTasksToCompleteOnShutdown ,
127140				this .taskDecorator , this .customizers );
128141	}
129142
@@ -136,7 +149,9 @@ public TaskExecutorBuilder maxPoolSize(int maxPoolSize) {
136149	public  TaskExecutorBuilder  allowCoreThreadTimeOut (boolean  allowCoreThreadTimeOut ) {
137150		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
138151				this .maxPoolSize , allowCoreThreadTimeOut , this .keepAlive ,
139- 				this .threadNamePrefix , this .taskDecorator , this .customizers );
152+ 				this .threadNamePrefix , this .awaitTermination ,
153+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
154+ 				this .customizers );
140155	}
141156
142157	/** 
@@ -147,7 +162,9 @@ public TaskExecutorBuilder allowCoreThreadTimeOut(boolean allowCoreThreadTimeOut
147162	public  TaskExecutorBuilder  keepAlive (Duration  keepAlive ) {
148163		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
149164				this .maxPoolSize , this .allowCoreThreadTimeOut , keepAlive ,
150- 				this .threadNamePrefix , this .taskDecorator , this .customizers );
165+ 				this .threadNamePrefix , this .awaitTermination ,
166+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
167+ 				this .customizers );
151168	}
152169
153170	/** 
@@ -158,7 +175,41 @@ public TaskExecutorBuilder keepAlive(Duration keepAlive) {
158175	public  TaskExecutorBuilder  threadNamePrefix (String  threadNamePrefix ) {
159176		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
160177				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
161- 				threadNamePrefix , this .taskDecorator , this .customizers );
178+ 				threadNamePrefix , this .awaitTermination ,
179+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
180+ 				this .customizers );
181+ 	}
182+ 
183+ 	/** 
184+ 	 * Set the maximum number of time that the executor is supposed to block on shutdown 
185+ 	 * in order to wait for remaining tasks to complete their execution before the rest of 
186+ 	 * the container continues to shut down. This is particularly useful if your remaining 
187+ 	 * tasks are likely to need access to other resources that are also managed by the 
188+ 	 * container. 
189+ 	 * @param awaitTermination the await termination to set 
190+ 	 * @return a new builder instance 
191+ 	 */ 
192+ 	public  TaskExecutorBuilder  awaitTermination (Duration  awaitTermination ) {
193+ 		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
194+ 				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
195+ 				this .threadNamePrefix , awaitTermination ,
196+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
197+ 				this .customizers );
198+ 	}
199+ 
200+ 	/** 
201+ 	 * Set whether the executor should wait for scheduled tasks to complete on shutdown, 
202+ 	 * not interrupting running tasks and executing all tasks in the queue. 
203+ 	 * @param waitForTasksToCompleteOnShutdown if executor needs to wait for the tasks to 
204+ 	 * complete on shutdown 
205+ 	 * @return a new builder instance 
206+ 	 */ 
207+ 	public  TaskExecutorBuilder  waitForTasksToCompleteOnShutdown (
208+ 			boolean  waitForTasksToCompleteOnShutdown ) {
209+ 		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
210+ 				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
211+ 				this .threadNamePrefix , this .awaitTermination ,
212+ 				waitForTasksToCompleteOnShutdown , this .taskDecorator , this .customizers );
162213	}
163214
164215	/** 
@@ -169,7 +220,8 @@ public TaskExecutorBuilder threadNamePrefix(String threadNamePrefix) {
169220	public  TaskExecutorBuilder  taskDecorator (TaskDecorator  taskDecorator ) {
170221		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
171222				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
172- 				this .threadNamePrefix , taskDecorator , this .customizers );
223+ 				this .threadNamePrefix , this .awaitTermination ,
224+ 				this .waitForTasksToCompleteOnShutdown , taskDecorator , this .customizers );
173225	}
174226
175227	/** 
@@ -199,7 +251,9 @@ public TaskExecutorBuilder customizers(Iterable<TaskExecutorCustomizer> customiz
199251		Assert .notNull (customizers , "Customizers must not be null" );
200252		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
201253				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
202- 				this .threadNamePrefix , this .taskDecorator , append (null , customizers ));
254+ 				this .threadNamePrefix , this .awaitTermination ,
255+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
256+ 				append (null , customizers ));
203257	}
204258
205259	/** 
@@ -229,7 +283,8 @@ public TaskExecutorBuilder additionalCustomizers(
229283		Assert .notNull (customizers , "Customizers must not be null" );
230284		return  new  TaskExecutorBuilder (this .queueCapacity , this .corePoolSize ,
231285				this .maxPoolSize , this .allowCoreThreadTimeOut , this .keepAlive ,
232- 				this .threadNamePrefix , this .taskDecorator ,
286+ 				this .threadNamePrefix , this .awaitTermination ,
287+ 				this .waitForTasksToCompleteOnShutdown , this .taskDecorator ,
233288				append (this .customizers , customizers ));
234289	}
235290
@@ -275,6 +330,10 @@ public <T extends ThreadPoolTaskExecutor> T configure(T taskExecutor) {
275330		map .from (this .allowCoreThreadTimeOut ).to (taskExecutor ::setAllowCoreThreadTimeOut );
276331		map .from (this .threadNamePrefix ).whenHasText ()
277332				.to (taskExecutor ::setThreadNamePrefix );
333+ 		map .from (this .awaitTermination ).asInt (Duration ::getSeconds )
334+ 				.to (taskExecutor ::setAwaitTerminationSeconds );
335+ 		map .from (this .waitForTasksToCompleteOnShutdown )
336+ 				.to (taskExecutor ::setWaitForTasksToCompleteOnShutdown );
278337		map .from (this .taskDecorator ).to (taskExecutor ::setTaskDecorator );
279338		if  (!CollectionUtils .isEmpty (this .customizers )) {
280339			this .customizers .forEach ((customizer ) -> customizer .customize (taskExecutor ));
0 commit comments