2016-04-30 55 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(); 
    } 

}