2016-04-30 57 views
0

我有一个单独的类因而Java并发 - singleton设计与监视线程

public final class HandlerCache { 
    //the cache maintains a handler per thread 
    private final Map<Thread, Handler> cache = new ConcurrentHashMap<>(); 

    private final Thread monitor; 

    private static final HandlerCache INSTANCE = new HandlerCache(); 

    private HandlerCache() { 
     monitor = new Thread() { 
     //periodically monitor cache and close handlers when a thread has died 
     } 
     monitor.start() 
    } 

    public static HandlerCache getInstance() { 
     return INSTANCE; 
    } 

    public Handler getHandler() throws Exception { 
     final Thread thread = Thread.currentThread(); 
     Handler handler = cache.get(thread); 

     if (!(handler == null)) 
      return handler; 

     handler = HandlerFactory.get(getHandlerFromName(thread.getName())); 
     cache.put(thread, handler); 
     return handler; 
    } 

} 

我泄露了单一实例来监视线程构造完成之前,有什么更好的办法?

将使缓存不稳定将解决这个问题?

+0

任何理由不使用一个ThreadLocal,而不是你的缓存? (注意:你的实现看起来不是线程安全的) – assylias

+0

感谢你的回复,我仍然需要在ThreadLocal的情况下维护线程和处理程序事件之间的映射,以便在线程死亡时关闭处理程序。线程类没有提供在线程停止之前调用的钩子,请您介绍一下线程安全问题,我注意到的是监视器线程在完全构建之前可以看到的对象,那就是原因对于这个问题 – user2677485

+0

getHandler方法不是原子的 - 所以工厂可能会在同一个线程中调用我,而不是一次 - 不知道这是否是一个问题(如果工厂的实现是朋友)。 – assylias

回答

0

不是在HandlerCache构造函数中启动线程,而是使用静态函数初始化实例,该静态函数首先构造HandlerCache然后启动线程。

1

正如user2677485所提到的,您应该使用ThreadLocal并实现initialValue方法。另一点是Handler实现应该实现finalize方法,以便GC在回收时调用此方法,并且可以清理资源。

的代码可以简化为类似如下:

public class HandlerCache { 

    private static final handlers = new ThreadLocal<Handler>() { 
     protected Handler initializeValue() { 
       return HandlerFactory.get(...); 
     } 
    }; 

    public static Handler getHandler() { 
     return handlers.get(); 
    } 

}