/* * 練習問題17.4 p.406 * 刈り取りスレッドを修正して、すべての割り当てられたリソースが開放されるまで、シャットダウンの後も * 生き続けるようにしなさい。 */ package ch17.ex17_04; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.util.HashMap; import java.util.Map; import javax.naming.Reference; public final class ResourceManager { final ReferenceQueue<Object> queue; // final Map<Reference<?>, Resource> refs; // Original, but error occurs... final Map<Reference, Resource> refs; final Thread reaper; boolean shutdown = false; public ResourceManager() { queue = new ReferenceQueue<Object>(); // refs = new HashMap<Reference<?>, Resource>(); // Original, but error occurs... refs = new HashMap<Reference, Resource>(); reaper = new ReaperThread(); reaper.start(); // ...リソースの初期化... } public synchronized void shutdown() { if (!shutdown) { shutdown = true; reaper.interrupt(); } } public synchronized Resource getResource(Object key) { if (shutdown) { throw new IllegalStateException(); } Resource res = new ResourceImpl(key); // Reference<?> ref = new PhantomReference<Object>(key, queue); // Original. but error occurs... Reference ref = new PhantomReference<Object>(key, queue); refs.put(ref, res); return res; } class ReaperThread extends Thread { public void run() { // 割り込まれるまで実行 while (true) { try { Reference<?> ref = queue.remove(); Resource res = null; synchronized(ResourceManager.this) { res = refs.get(ref); refs.remove(ref); } res.release(); ref.clear(); } catch (InterruptedException ex) { break; // すべて終了 } } } } }