/*
* 練習問題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; // すべて終了
}
}
}
}
}