1

hahsmapを含むシングルトンクラスがあります。ハッシュマップはクラス変数として初期化されます。サイズを追加して印刷すると変更されたため、このマップは正しく更新されますが、別のスレッドから呼び出すと、マップは常に空になります。これが発生する可能性がある特別な理由はありますか?

これで違いが生じる場合は、ConccurentHashMapを使用しています。

ありがとう

Singleton decleration:

    public class ClientRegistryDetailsSingleton {

        private static ClientRegistryDetailsSingleton instance = null;
        private ConcurrentHashMap<String, Integer> tickerToNumberRegistered = new ConcurrentHashMap<String,Integer>();


        protected ClientRegistryDetailsSingleton() {
             // Exists only to defeat instantiation.
        }

        public static ClientRegistryDetailsSingleton getInstance() {
            if(instance == null) {
               instance = new ClientRegistryDetailsSingleton();
            }
            return instance;
        }

        public void setTickerToNumberRegistered(ConcurrentHashMap<String, Integer> tickerToNumberRegistered) {
            this.tickerToNumberRegistered = tickerToNumberRegistered;
        }

        public ConcurrentHashMap<String, Integer> getTickerToNumberRegistered() {
            return tickerToNumberRegistered;
        }


    public void addToClienets(String ticker){}

    public void removeFromClients(String ticker){}
}

別のスレッドから呼び出す:

String[] splitForTicker = message.split(",");

        ConcurrentHashMap<String, Integer> map = ClientRegistryDetailsSingleton.getInstance().getTickerToNumberRegistered();
        System.out.println("The number of items in the map from senders persepctive" + map.size());

出力:

The number of items in the map from senders persepctive 0
2012-11-12 14:29:12,495 [Process messages received] INFO  com.feed.feedReceive.ProcessFeedStreamLine - Successfully received a message from the feed
The number of items in the map from senders persepctive 0
1 :the size of the map now someone has added
2012-11-12 14:29:15,495 [Process messages received] INFO  com.feed.feedReceive.ProcessFeedStreamLine - Successfully received a

フィードからのメッセージ送信者からのマップ内のアイテムの数persepctive0

シングルトンの新しいコード

public class ClientRegistryDetailsSingleton {

    private static ClientRegistryDetailsSingleton instance = new ClientRegistryDetailsSingleton();
    private volatile ConcurrentHashMap<String, Integer> tickerToNumberRegistered = new ConcurrentHashMap<String,Integer>();

    protected ClientRegistryDetailsSingleton() {
         // Exists only to defeat instantiation.
    }

    public static synchronized ClientRegistryDetailsSingleton getInstance() {
        return instance;
    }

    public synchronized ConcurrentHashMap<String, Integer> getTickerToNumberRegistered() {
        return tickerToNumberRegistered;
    }

    public void addToClienets(String ticker){}

    public void removeFromClients(String ticker){}
}
4

3 に答える 3

3

投稿されたコードには競合状態があり、2 つのスレッドが呼び出さgetInstance()れ、シングルトンがまだ構築されていない場合、シングルトンの複数のインスタンスが構築される可能性があります。

public static ClientRegistryDetailsSingleton getInstance() {
    if(instance == null) {                                   // Line 1
        instance = new ClientRegistryDetailsSingleton();     // Line 2
    }
}

2 つのスレッドの可能な実行、T1およびT2:

  • T1 は 1 行目でチェックを実行し、if分岐に入ります。
  • T1 は中断されたinstanceままnullです。
  • T2 は 1 行目でチェックを実行し、if分岐に入ります。
  • T2 はクラスを構築し、に割り当てinstanceます。
  • T2 はinstance発信者に戻ります。
  • T2 は中断されます。
  • T1 が再び開始され、別のインスタンスを構築して に割り当てますinstance

単一インスタンスの構築は、スレッドセーフでなければなりません。考えられる解決策は次のとおりです。

  • メソッドを作成しgetInstance()ますsynchronized
  • 遅延初期化を使用しないでください (可能な場合):

    private static final ClientRegistryDetailsSingleton instance =
        new ClientRegistryDetailsSingleton();
    
于 2012-11-12T14:11:31.653 に答える
0

DCLアンチパターンの実装:http://en.wikipedia.org/wiki/Double_checked_locking

public class ClientRegistryDetailsSingleton {

    private static volatile ClientRegistryDetailsSingleton instance = null;

    private final ConcurrentHashMap<String, Integer> tickerToNumberRegistered = new ConcurrentHashMap<String,Integer>();


    private ClientRegistryDetailsSingleton() {
         // Exists only to defeat instantiation. 
         // please not that constructor should be private
    }

    public static ClientRegistryDetailsSingleton getInstance() {
         if (instance == null) {
               synchronized(ClientRegistryDetailsSingleton.class){
                  if(instance == null)
                    instance = new ClientRegistryDetailsSingleton();
               }
         }
         return instance;
    }

    //You should not break encapsulation and allow a link to HashMap escape
    private void setTickerToNumberRegistered(ConcurrentHashMap<String, Integer> tickerToNumberRegistered) {
        this.tickerToNumberRegistered = tickerToNumberRegistered;
    }

    //You should not break encapsulation and allow a link to HashMap escape
    private ConcurrentHashMap<String, Integer> getTickerToNumberRegistered() {
    }

     //I omitted the access to the hash map it's likely that some additional params required
     public void addToClienets(String ticker){}

     //I omitted the access to the hash map it's likely some additional params are required
     public void removeFromClients(String ticker){}
}

これは同期の例としてのみ示しましたが、実際には、シングルトンを列挙型として実装する必要があります。Javaで列挙型をシングルトンとして使用するための最良のアプローチは何ですか。

于 2012-11-12T14:37:45.513 に答える
0

ハッシュマップを次のように定義します

private volatile ConcurrentHashMap<String, Integer>

volatile キーワードは、変数の状態が別のスレッドによっていつでも変更される可能性があることを JVM に警告するため、変数をローカルにキャッシュしてはなりません。

インスタンスを揮発性として定義することも必要になる場合があります。

于 2012-11-12T14:10:51.780 に答える