@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2012 the original author or authors .
* Copyright 2002 - 2013 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
@ -20,6 +20,7 @@ import java.util.concurrent.ExecutorService;
@@ -20,6 +20,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler ;
import java.util.concurrent.ThreadFactory ;
import java.util.concurrent.ThreadPoolExecutor ;
import java.util.concurrent.TimeUnit ;
import org.apache.commons.logging.Log ;
import org.apache.commons.logging.LogFactory ;
@ -54,6 +55,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
@@ -54,6 +55,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
private boolean waitForTasksToCompleteOnShutdown = false ;
private int awaitTerminationSeconds = 0 ;
private String beanName ;
private ExecutorService executor ;
@ -85,9 +88,17 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
@@ -85,9 +88,17 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
}
/ * *
* Set whether to wait for scheduled tasks to complete on shutdown .
* < p > Default is "false" . Switch this to "true" if you prefer
* fully completed tasks at the expense of a longer shutdown phase .
* Set whether to wait for scheduled tasks to complete on shutdown ,
* not interrupting running tasks and executing all tasks in the queue .
* < p > Default is "false" , shutting down immediately through interrupting
* ongoing tasks and clearing the queue . Switch this flag to "true" if you
* prefer fully completed tasks at the expense of a longer shutdown phase .
* < p > Note that Spring ' s container shutdown continues while ongoing tasks
* are being completed . If you want this executor to block and wait for the
* termination of tasks before the rest of the container continues to shut
* down - e . g . in order to keep up other resources that your tasks may need - ,
* set the { @link # setAwaitTerminationSeconds "awaitTerminationSeconds" }
* property instead of or in addition to this property .
* @see java . util . concurrent . ExecutorService # shutdown ( )
* @see java . util . concurrent . ExecutorService # shutdownNow ( )
* /
@ -95,6 +106,33 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
@@ -95,6 +106,33 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
this . waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown ;
}
/ * *
* Set the maximum number of seconds that this executor is supposed to block
* on shutdown in order to wait for remaining tasks to complete their execution
* before the rest of the container continues to shut down . This is particularly
* useful if your remaining tasks are likely to need access to other resources
* that are also managed by the container .
* < p > By default , this executor won ' t wait for the termination of tasks at all .
* It will either shut down immediately , interrupting ongoing tasks and clearing
* the remaining task queue - or , if the
* { @link # setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown" }
* flag has been set to { @code true } , it will continue to fully execute all
* ongoing tasks as well as all remaining tasks in the queue , in parallel to
* the rest of the container shutting down .
* < p > In either case , if you specify an await - termination period using this property ,
* this executor will wait for the given time ( max ) for the termination of tasks .
* As a rule of thumb , specify a significantly higher timeout here if you set
* "waitForTasksToCompleteOnShutdown" to { @code true } at the same time ,
* since all remaining tasks in the queue will still get executed - in contrast
* to the default shutdown behavior where it ' s just about waiting for currently
* executing tasks that aren ' t reacting to thread interruption .
* @see java . util . concurrent . ExecutorService # shutdown ( )
* @see java . util . concurrent . ExecutorService # awaitTermination
* /
public void setAwaitTerminationSeconds ( int awaitTerminationSeconds ) {
this . awaitTerminationSeconds = awaitTerminationSeconds ;
}
public void setBeanName ( String name ) {
this . beanName = name ;
}
@ -145,6 +183,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
@@ -145,6 +183,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
/ * *
* Perform a shutdown on the ThreadPoolExecutor .
* @see java . util . concurrent . ExecutorService # shutdown ( )
* @see java . util . concurrent . ExecutorService # shutdownNow ( )
* @see # awaitTerminationIfNecessary ( )
* /
public void shutdown ( ) {
if ( logger . isInfoEnabled ( ) ) {
@ -156,6 +196,31 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
@@ -156,6 +196,31 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
else {
this . executor . shutdownNow ( ) ;
}
awaitTerminationIfNecessary ( ) ;
}
/ * *
* Wait for the executor to terminate , according to the value of the
* { @link # setAwaitTerminationSeconds "awaitTerminationSeconds" } property .
* /
private void awaitTerminationIfNecessary ( ) {
if ( this . awaitTerminationSeconds > 0 ) {
try {
if ( ! this . executor . awaitTermination ( this . awaitTerminationSeconds , TimeUnit . SECONDS ) ) {
if ( logger . isWarnEnabled ( ) ) {
logger . warn ( "Timed out while waiting for executor" +
( this . beanName ! = null ? " '" + this . beanName + "'" : "" ) + " to terminate" ) ;
}
}
}
catch ( InterruptedException ex ) {
if ( logger . isWarnEnabled ( ) ) {
logger . warn ( "Interrupted while waiting for executor" +
( this . beanName ! = null ? " '" + this . beanName + "'" : "" ) + " to terminate" ) ;
}
Thread . currentThread ( ) . interrupt ( ) ;
}
}
}
}