diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index 99bbd53c72deb2125738f6b88f9ebf01be2f12c5..7df62046c8c79d64008a3b4e61a23461a3a95737 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -906,6 +906,13 @@ public class I2PAppContext { public void addShutdownTask(Runnable task) { _shutdownTasks.add(task); } + + /** + * @since 0.9.53 + */ + public void removeShutdownTask(Runnable task) { + _shutdownTasks.remove(task); + } /** * @return an unmodifiable Set diff --git a/core/java/src/net/i2p/util/SimpleTimer2.java b/core/java/src/net/i2p/util/SimpleTimer2.java index b6c6deaef72a5b926db4ad8197b24506c9e10974..f2723dbb73b7e8c012836b8e958e83624e694b4e 100644 --- a/core/java/src/net/i2p/util/SimpleTimer2.java +++ b/core/java/src/net/i2p/util/SimpleTimer2.java @@ -41,6 +41,8 @@ public class SimpleTimer2 { private final String _name; private final AtomicInteger _count = new AtomicInteger(); private final int _threads; + private final I2PAppContext _context; + private final Runnable _shutdown; /** * To be instantiated by the context. @@ -64,14 +66,15 @@ public class SimpleTimer2 { * @since 0.9 */ protected SimpleTimer2(I2PAppContext context, String name, boolean prestartAllThreads) { + _context = context; _name = name; long maxMemory = SystemVersion.getMaxMemory(); _threads = (int) Math.max(MIN_THREADS, Math.min(MAX_THREADS, 1 + (maxMemory / (32*1024*1024)))); _executor = new CustomScheduledThreadPoolExecutor(_threads, new CustomThreadFactory()); if (prestartAllThreads) _executor.prestartAllCoreThreads(); - // don't bother saving ref to remove hook if somebody else calls stop - context.addShutdownTask(new Shutdown()); + _shutdown = new Shutdown(); + context.addShutdownTask(_shutdown); } /** @@ -79,7 +82,7 @@ public class SimpleTimer2 { */ private class Shutdown implements Runnable { public void run() { - stop(); + stop(false); } } @@ -89,6 +92,20 @@ public class SimpleTimer2 { * Cannot be restarted. */ public void stop() { + stop(true); + } + + /** + * Stops the SimpleTimer. + * Subsequent executions should not throw a RejectedExecutionException. + * Cannot be restarted. + * + * @param removeTask true to unregister the shutdown hook + * @since 0.9.53 + */ + private void stop(boolean removeTask) { + if (removeTask) + _context.removeShutdownTask(_shutdown); _executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); _executor.shutdownNow(); }