私はCassandraと協力してDatastax Javaドライバを使用しています。準備した文をキャッシュして再利用しようとしています。putIfAbsentで「get/check/put」の使用を置き換えます。
private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>();
public BoundStatement getStatement(String cql) {
Session session = TestUtils.getInstance().getSession();
PreparedStatement ps = holder.get(cql);
// no statement is cached, create one and cache it now.
if (ps == null) {
synchronized (this) {
ps = holder.get(cql);
if (ps == null) {
ps = session.prepare(cql);
holder.put(cql, ps);
}
}
}
return ps.bind();
}
私はそれは、スレッドセーフであることを確認する必要がありますのでマイ上記getStatement
方法は、複数のスレッドによって呼び出されます。私はJava 7を使用しているので、残念ながらcomputeIfAbsent
を使用することはできません。
静的アナライズツールに対してコードを実行したとき、Java 7のコードを書く上でより良い方法があると思うようになりました。
Might be better to replace use of get/check/put with putIfAbsent
更新:
public BoundStatement getStatement(String cql) {
Session session = TestUtils.getInstance().getSession();
PreparedStatement ps = holder.get(cql);
// no statement is cached, create one and cache it now.
if (ps == null) {
ps = session.prepare(cql);
PreparedStatement old = holder.putIfAbsent(cql, ps);
if (old!=null)
ps=old;
}
return ps.bind();
}
これは、いくつかの理由で間違っています。 1つは、インスタンスを同期させて静的フィールドを保護することです。もう1つは、同期とロックフリーのコレクションを混在させることです。 – shmosel
あなたのアプローチでは、準備された文のインスタンスをキャッシュする価値があると仮定しています。それは...ですか?毎回新しいインスタンスを作成する実際のパフォーマンスヒットは何ですか? (本物の質問;私はそれらを扱うことはめったにないので、どれくらい重いか分かりません)。 –
これらのプリペアドステートメントをキャッシュしないと、すべてのログに警告メッセージ '既に準備されたクエリを再準備しています。同じクエリを2回以上準備することは、一般的に反パターンであり、パフォーマンスに影響する可能性があることに注意してください。この文を一度だけ準備することを検討してください.' datastax java driverから。ここには[質問](http://stackoverflow.com/questions/22915840/re-using-preparedstatement-when-using-datastax-cassandra-driver)があります。そのことについてもっと詳しく述べていますので、私は準備文を再利用することにしました。 – john