2016-04-30 14 views
0

とシングルトンデザイン私は、コンストラクタが終了する前に、私は、監視スレッドにシングルトンインスタンスをリークしていますので、Javaの同時実行 - 監視スレッド

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; 
    } 

} 

シングルトンクラスを持って、より良い方法は何ですか?

キャッシュをvolatileにすると問題が解決されますか?

+0

代わりにあなたのキャッシュのThreadLocalのを使用しない任意の理由? (サイドノート:あなたの実装はスレッドセーフではありません) – assylias

+0

返信いただきありがとうございます。スレッドが終了したときにハンドラを閉じるために、ThreadLocalの場合はスレッドとハンドライベントの間のマッピングを維持する必要があります。スレッドクラスは、スレッドが停止する前に呼び出されるフックを提供しません。スレッド安全性の問題を説明してください。完全に構築される前にオブジェクトがモニタスレッドに表示されていることがわかります。この質問のため – user2677485

+0

getHandlerメソッドはアトミックではありません。そのため、同じスレッドで工場が1回以上呼び出される可能性があります。問題があるかどうかは不明です(ファクトリの実装では友達)。 – 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(); 
    } 

} 
関連する問題