diff --git a/batik-util/src/main/java/org/apache/batik/util/CleanerThread.java b/batik-util/src/main/java/org/apache/batik/util/CleanerThread.java index 2199893651..b88ae584b4 100644 --- a/batik-util/src/main/java/org/apache/batik/util/CleanerThread.java +++ b/batik-util/src/main/java/org/apache/batik/util/CleanerThread.java @@ -22,6 +22,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.lang.ref.PhantomReference; /** @@ -34,14 +36,16 @@ Licensed to the Apache Software Foundation (ASF) under one or more */ public class CleanerThread extends Thread { - static volatile ReferenceQueue queue = null; - static CleanerThread thread = null; + static volatile ReferenceQueue queue = null; + static CleanerThread thread = null; + /* latch to signal CleanerThread shutdown request */ + private CountDownLatch shutdownLatch = new CountDownLatch(1); - public static ReferenceQueue getReferenceQueue() { + public static ReferenceQueue getReferenceQueue() { - if ( queue == null ) { - synchronized (CleanerThread.class) { - queue = new ReferenceQueue(); + synchronized (CleanerThread.class) { + if ( queue == null ) { + queue = new ReferenceQueue<>(); thread = new CleanerThread(); } } @@ -94,29 +98,38 @@ public PhantomReferenceCleared(Object o) { protected CleanerThread() { super("Batik CleanerThread"); - setDaemon(true); start(); } + @Override public void run() { - while(true) { - try { - Reference ref; - try { - ref = queue.remove(); + try { + while(!shutdownLatch.await(100, TimeUnit.SECONDS)) { + Reference ref; + do { + ref = queue.poll(); // System.err.println("Cleaned: " + ref); - } catch (InterruptedException ie) { - continue; - } - - if (ref instanceof ReferenceCleared) { - ReferenceCleared rc = (ReferenceCleared)ref; - rc.cleared(); - } - } catch (ThreadDeath td) { - throw td; - } catch (Throwable t) { - t.printStackTrace(); + if (ref != null && ref instanceof ReferenceCleared) { + ReferenceCleared rc = (ReferenceCleared)ref; + rc.cleared(); + } + } while (ref != null); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Request CleanerThread shutdown and wait for it to finish. + */ + public static void shutdown() throws InterruptedException { + synchronized (CleanerThread.class) { + if (thread != null) { + thread.shutdownLatch.countDown(); + thread.join(); + queue = null; + thread = null; } } } diff --git a/batik-util/src/main/java/org/apache/batik/util/HaltingThread.java b/batik-util/src/main/java/org/apache/batik/util/HaltingThread.java index eeb84e4325..94937a6838 100644 --- a/batik-util/src/main/java/org/apache/batik/util/HaltingThread.java +++ b/batik-util/src/main/java/org/apache/batik/util/HaltingThread.java @@ -31,7 +31,7 @@ public class HaltingThread extends Thread { /** * Boolean indicating if this thread has ever been 'halted'. */ - protected boolean beenHalted = false; + protected volatile boolean beenHalted = false; public HaltingThread() { }