workQueue, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
@@ -54,6 +70,31 @@
@Override
protected void afterExecute(Runnable r, Throwable t) {
activeCount.decrementAndGet();
+
+ if (t == null) {
+ if (Thread.currentThread() instanceof TaskThread) {
+ TaskThread currentTaskThread = (TaskThread) Thread.currentThread();
+ if (currentTaskThread.getCreationTime() < StandardContext.lastContextStoppedTime.longValue()) {
+ long lastTime = lastTimeThreadKilledItself.longValue();
+ if (lastTime + threadRenewalRateMs < System.currentTimeMillis()) {
+ if (lastTimeThreadKilledItself.compareAndSet(lastTime, System.currentTimeMillis())) {
+ //OK, it's really time to dispose of this thread
+
+ final String msg = "Stopping thread " + currentTaskThread.getName()
+ + " to avoid potential memory leaks after a context was stopped.";
+ currentTaskThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ // yes, swallow the exception
+ log.info(msg);
+ }
+ });
+ throw new RuntimeException(msg);
+ }
+ }
+ }
+ }
+ }
}
@Override
--- webapps/docs/config/executor.xml (revision 1000553)
+++ webapps/docs/config/executor.xml (working copy)
@@ -98,6 +98,9 @@
(int) The minimum number of threads always kept alive, default is 25
+
+ (int) Maximum number of tasks for the pending task queue, default is Integer.MAX_VALUE
+
(int) The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less
or equal to minSpareThreads. Default value is 60000
(1 minute)