gpt4 book ai didi

java - 以线程安全的方式缓存preparestatement?

转载 作者:行者123 更新时间:2023-12-02 08:58:43 25 4
gpt4 key购买 nike

我正在缓存准备好的语句,以便在使用datastax java驱动程序(cassandra)时不必再次准备它。以下是我的代码,它可以工作:

  private static final ConcurrentHashMap<String, PreparedStatement> cache = new ConcurrentHashMap<>();

public ResultSetFuture send(final String cql, final Object... values) {
return executeWithSession(new SessionCallable<ResultSetFuture>() {
@Override
public ResultSetFuture executeWithSession(Session session) {
BoundStatement bs = getStatement(cql, values);
bs.setConsistencyLevel(consistencyLevel);
return session.executeAsync(bs);
}
});
}

private BoundStatement getStatement(final String cql, final Object... values) {
Session session = getSession();
PreparedStatement ps = cache.get(cql);
// no statement cached, create one and cache it now.
// below line is causing thread safety issue..
if (ps == null) {
ps = session.prepare(cql);
PreparedStatement old = cache.putIfAbsent(cql, ps);
if (old != null)
ps = old;
}
return ps.bind(values);
}


但是问题是 send方法将被多个线程调用,因此我怀疑我的 getStatement方法由于 if (ps == null)检查而不是线程安全的。如何使它成为线程安全的?

我想避免使用 synchronize关键字,所以想看看是否有更好的方法。到目前为止,我正在使用Java 7。

最佳答案

您可以改用computeIfAbsent。根据文档,它是:


  如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值,除非为null,否则将其输入此映射。整个方法调用是原子执行的,因此每个键最多可应用一次该功能。在进行计算时,可能会阻止其他线程在此映射上进行的某些尝试的更新操作,因此计算应简短而简单,并且不得尝试更新此映射的任何其他映射。


该代码如下所示:

private BoundStatement getStatement(final String cql, final Object... values) {
PreparedStatement pr = cache.computeIfAbsent(
query, key -> session.prepare(key));
return pr.bind(values);
}


虽然,因为准备工作可能需要更长的时间,所以不建议...我会改用显式锁...

附言请注意, Java driver 4.x has built-in cache,因此可以多次准备相同的语句。

关于java - 以线程安全的方式缓存preparestatement?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60329855/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com