我的下方法线程是否安全?这个方法是Singleton类。
private static final Map<String, PreparedStatement> holder = new ConcurrentHashMap<>();
public BoundStatement getStatement(String cql) {
Session session = TestUtils.getInstance().getSession();
PreparedStatement ps = holder.get(cql);
if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait.
synchronized {
ps = holder.get(cql);
if (ps == null) {
ps = session.prepare(cql);
holder.put(cql, ps);
}
}
}
return ps.bind();
}
我正在使用Cassandra并使用datastax java驱动程序,因此我重用了预处理语句,这就是我在这里缓存它的原因。 Prepared Statement和BoundStatement。
有没有更好的方法使我的getStatement
方法线程安全(如果它是线程安全的)而不是像这样使用synchronized块?对于这类操作可能是线程安全的任何其他数据结构?我正在使用Java 7。
答案 0 :(得分:2)
由于.putIfAbsent在Java7中,您可以使用它:
private static final ConcurrentHashMap<String, PreparedStatement> holder = new ConcurrentHashMap<>();
public BoundStatement getStatement(String cql) {
Session session = TestUtils.getInstance().getSession();
PreparedStatement ps = holder.get(cql);
if(ps == null) { // If "ps" is already present in cache, then we don't have to synchronize and make threads wait.
if (holder.putIfAbsent(cql, session.prepare(cql)) != null) {
// Someone else got there before, handle
}
}
return ps.bind();
}
请注意,putIfAbsent仍然在内部使用相同的同步。
答案 1 :(得分:1)
如果您正在寻找某种形式的memoization,那么这是您在Java 7中可以做的最好/最简单.Guava有一个可以使用的计算Cache实现,而Java 8有computeIfAbsent
Map
界面中的方法,但你在这里显然是运气不好。
如果您可以在空竞赛中创建对象,例如Alexey的答案建议,那将是最佳解决方案。如果不能,那么您的实现既线程安全又合理。
这是一种双重检查锁定的形式,但是,通过此实现,您可以使用CHM的put
和get
方法确保在排序之前发生。