Я кэширую подготовленное заявление, поэтому мне не нужно готовить его снова при работе с драйвером данных 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.