@@ -22,6 +22,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2222import java .lang .ref .ReferenceQueue ;
2323import java .lang .ref .SoftReference ;
2424import java .lang .ref .WeakReference ;
25+ import java .util .concurrent .CountDownLatch ;
26+ import java .util .concurrent .TimeUnit ;
2527import java .lang .ref .PhantomReference ;
2628
2729/**
@@ -34,15 +36,18 @@ Licensed to the Apache Software Foundation (ASF) under one or more
3436 */
3537public class CleanerThread extends Thread {
3638
37- static volatile ReferenceQueue queue = null ;
39+ static volatile ReferenceQueue <?> queue = null ;
3840 static CleanerThread thread = null ;
41+ /* latch to signal CleanerThread shutdown request */
42+ private static CountDownLatch shutdownLatch = null ;
3943
40- public static ReferenceQueue getReferenceQueue () {
44+ public static ReferenceQueue <?> getReferenceQueue () {
4145
42- if ( queue == null ) {
43- synchronized ( CleanerThread . class ) {
44- queue = new ReferenceQueue ();
46+ synchronized ( CleanerThread . class ) {
47+ if ( queue == null ) {
48+ queue = new ReferenceQueue <> ();
4549 thread = new CleanerThread ();
50+ shutdownLatch = new CountDownLatch (1 );
4651 }
4752 }
4853 return queue ;
@@ -94,29 +99,42 @@ public PhantomReferenceCleared(Object o) {
9499
95100 protected CleanerThread () {
96101 super ("Batik CleanerThread" );
97- setDaemon (true );
98102 start ();
99103 }
100104
105+ @ Override
101106 public void run () {
102- while ( true ) {
103- try {
104- Reference ref ;
105- try {
106- ref = queue .remove ();
107+ try {
108+ while (! shutdownLatch . await ( 100 , TimeUnit . SECONDS )) {
109+ Reference <?> ref ;
110+ do {
111+ ref = queue .poll ();
107112 // System.err.println("Cleaned: " + ref);
108- } catch (InterruptedException ie ) {
109- continue ;
110- }
111-
112- if (ref instanceof ReferenceCleared ) {
113- ReferenceCleared rc = (ReferenceCleared )ref ;
114- rc .cleared ();
115- }
116- } catch (ThreadDeath td ) {
117- throw td ;
118- } catch (Throwable t ) {
119- t .printStackTrace ();
113+ if (ref != null && ref instanceof ReferenceCleared ) {
114+ ReferenceCleared rc = (ReferenceCleared )ref ;
115+ rc .cleared ();
116+ }
117+ } while (ref != null );
118+ }
119+ } catch (InterruptedException e ) {
120+ e .printStackTrace ();
121+ } finally {
122+ synchronized (CleanerThread .class ) {
123+ queue = null ;
124+ thread = null ;
125+ shutdownLatch = null ;
126+ }
127+ }
128+ }
129+
130+ /**
131+ * Request CleanerThread shutdown and wait for it to finish.
132+ */
133+ public static void shutdown () throws InterruptedException {
134+ synchronized (CleanerThread .class ) {
135+ if (shutdownLatch != null ) {
136+ shutdownLatch .countDown ();
137+ thread .join ();
120138 }
121139 }
122140 }
0 commit comments