Don't start shutdown hook threads more than once.

This commit is contained in:
akwizgran
2011-11-19 17:23:18 +00:00
parent bc7d882af6
commit b2226067e1
2 changed files with 20 additions and 12 deletions

View File

@@ -15,14 +15,18 @@ class ShutdownManagerImpl implements ShutdownManager {
hooks = new HashMap<Integer, Thread>(); hooks = new HashMap<Integer, Thread>();
} }
public synchronized int addShutdownHook(Runnable runnable) { public synchronized int addShutdownHook(Runnable r) {
int handle = nextHandle++; int handle = nextHandle++;
Thread hook = new Thread(runnable); Thread hook = createThread(r);
hooks.put(handle, hook); hooks.put(handle, hook);
Runtime.getRuntime().addShutdownHook(hook); Runtime.getRuntime().addShutdownHook(hook);
return handle; return handle;
} }
protected Thread createThread(Runnable r) {
return new Thread(r);
}
public synchronized boolean removeShutdownHook(int handle) { public synchronized boolean removeShutdownHook(int handle) {
Thread hook = hooks.remove(handle); Thread hook = hooks.remove(handle);
if(hook == null) return false; if(hook == null) return false;

View File

@@ -45,9 +45,14 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
} }
@Override @Override
public synchronized int addShutdownHook(Runnable runnable) { public synchronized int addShutdownHook(Runnable r) {
if(!initialised) initialise(); if(!initialised) initialise();
return super.addShutdownHook(new RunOnce(runnable)); return super.addShutdownHook(r);
}
@Override
protected Thread createThread(Runnable r) {
return new StartOnce(r);
} }
// Locking: this // Locking: this
@@ -122,19 +127,18 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
} }
} }
private static class RunOnce implements Runnable { private static class StartOnce extends Thread {
private final Runnable runnable;
private final AtomicBoolean called = new AtomicBoolean(false); private final AtomicBoolean called = new AtomicBoolean(false);
private RunOnce(Runnable runnable) { private StartOnce(Runnable r) {
this.runnable = runnable; super(r);
} }
public void run() { @Override
// Ensure the runnable only runs once public void start() {
if(called.getAndSet(true)) return; // Ensure the thread is only started once
runnable.run(); if(!called.getAndSet(true)) super.start();
} }
} }