0

私は異なる変数を持つモデルを持っています。私はモデルが作成され、サーバの起動時にスレッドの安全な方法でHashMapの値をインクリメントせずに、高性能を維持しながらインクリメントしますか?

public class Model implements Serializable{ 

    public final static int STATE_INIT = 0; 
    public final static int STATE_READY = 1; 

    private Integer state = STATE_INIT; 
    private HashMap<Integer,Integer>pageRequests = new HashMap<>(); 
    private HashMap<Integer,Integer>impr = new HashMap<>(); 
    private HashMap<Integer,Integer>clicks = new HashMap<>(); 

    public void incrementPageRequests(int accountId){ 

    if(this.pageRequests.get(accountId) != null){ 
     this.pageRequests.put(accountId,this.pageRequests.get(accountId) +1); 
    } else { 
     this.pageRequests.put(accountId,1); 
    } 
} 

public void incrementImprServed(int accountId){ 

    if(this.imprServed.get(accountId) != null){ 
     this.imprServed.put(accountId,this.imprServed.get(accountId) +1); 
    } else { 
     this.imprServed.put(accountId,1); 
    } 
} 

public void incrementClicksServed(int accountId){ 

    if(this.clicksServed.get(accountId) != null){ 
     this.clicksServed.put(accountId,this.clicksServed.get(accountId) +1); 
    } else { 
     this.clicksServed.put(accountId,1); 
    } 
} 

}

は、今ではシングルトンBeanです。私はいくつかのいずれかがエンドポイントを呼び出すとき

/増分に

@GetMapping(path = "/increment") 
    public String increment(){ 
     model.incrementPageRequests(1); 
     return "Okay"; 
    } 

をモデルのハッシュマップを変更することができるようにしたい私は、メソッドがスレッドセーフになっ​​キーワードを追加する際に現在このincrementPageRequestはスレッドセーフではありませんしかし、同期は非常にコストがかかり、高いスループットとパフォーマンスを求めていると聞いています。

どのように同期させずに高性能を維持することができますか?

更新

が同時のHashMapで試しても、それは私はそれが同時ハッシュマップに

if(this.pageRequests.get(accountId) != null){ 
      this.pageRequests.put(accountId,this.pageRequests.get(accountId) +1); 
     } else { 
      System.out.println("Here"); 
      this.pageRequests.putIfAbsent(accountId,1); 
     } 
を動作するように私はこのロジックを変更するにはどうすればよいのAPI

への同時通話をテストするためのJMeterを使用しています失敗

+0

同期は非常に高価です。それがボトルネックになると思うなら、いくつかの証拠を得る必要があります。 'ConcurrentHashMap'はあなたがバグをコードしていない限り、失敗しません。あなたが何を求めているのか不明です。 – EJP

+0

あなたは 'synchronized'がこのREST呼び出しの* slow *セクションになると思いますか?本当に? – Nim

+0

私はそれについてはわかりませんbutiはハッシュマップを同時ハッシュマップに変更しようとしましたが、動作しません。あなたは私の方法で変更する必要があることを私に許してもらえますか? @EJP – INFOSYS

答えて

0

最初に、ベンチマークを作成してから、どのソリューションが役立つかを決定します。

また、あなたは(あまりにも他の方法で)ここで少し冗長な作業をやっている:

if(this.pageRequests.get(accountId) != null){ 
    this.pageRequests.put(accountId,this.pageRequests.get(accountId) +1); 
} else { 
    this.pageRequests.put(accountId,1); 
} 

代わり

final String value = this.pageRequests.get(accountId); 
if(value == null){ 
    this.pageRequests.put(accountId, 1); 
    return; 
} 
this.pageRequests.put(accountId, value + 1); 

今、あなたは以下のマップに1件の読み取りアクセスを持っています。 「それは同時ハッシュマップで動作するように私はこのロジックを変更するにはどうすればよい」あなたの2つ目の質問について

これを変更:

private HashMap<Integer, Integer> pageRequests = new HashMap<>(); 
すぎ

private Map<Integer, Integer> pageRequests = new ConcurrentHashMap<>(); 

インタフェースはあなたが単純なことができますとしてのプライベートフィールドを維持マップの実装を変更します。

+0

throw起動時にnullポインタを実行すると、pagerequesthashmapが空です。キャッチしようとしても問題は解決しません。 – INFOSYS

+0

Integerに変更してから、500の同時リクエストを発生させても、増分値は434です。 – INFOSYS

関連する問題