我正在使用 Cassandra 并使用 Datastax Java 驱动程序。我正在尝试通过缓存来重用准备好的语句。
private static final ConcurrentHashMap<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) {
holder.putIfAbsent(cql, session.prepare(cql));
}
return ps.bind();
}
Prepared Statement和 BoundStatement datastax java 驱动程序。
此 getStatement
方法将由多个线程调用,因此我必须确保它是线程安全的。我正在使用 Java 7。
如果我们得到两个相同的 cql 准备好的语句,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) {
synchronized (this) {
ps = holder.get(cql);
if (ps == null) {
ps = session.prepare(cql);
holder.put(cql, ps);
}
}
}
return ps.bind();
}
最佳答案
您的代码存在竞争条件,可能会导致任何 cql
参数调用 session.prepare(cql)
两次(或更多次)。在这种情况下,putIfAbsent
并没有真正比普通的 put
提供任何优势。
如果您使用的是 Java 8,您可以高效地编写此代码,而无需使用以下命令创建重复项
PreparedStatement ps = holder.computeIfAbsent(cql, key -> session.prepare(key));
关于java - "putIfAbsent"在CHM中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40874129/