저는 Cassandra와 Datastax Java 드라이버를 사용하고 있습니다. 준비된 문장을 캐싱하여 다시 사용하려고합니다. 내 위의 getStatement
방법은 여러 스레드에 의해 호출됩니다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();
}
그래서 그것이 스레드 안전 확인해야합니다. Java 7에서 작동하므로 불행히도 computeIfAbsent
을 사용할 수 없습니다.
static anaylysis 툴에 대해 코드를 실행했을 때 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();
}
이 여러 가지 이유로 잘못되었습니다. 한 가지 예를 들어, 인스턴스를 동기화하여 정적 필드를 지키고 있습니다. 다른 하나는 동기화 및 잠금 해제 콜렉션을 혼합하는 것입니다. – shmosel
접근 방식은 준비된 명령문 인스턴스를 캐싱 할 가치가 있다고 가정합니다. 그렇지? 매번 새로운 인스턴스를 생성 할 때 실제 성능에 미치는 영향은 무엇입니까? (진짜 질문, 나는 그들과 거의 거래하지 않으므로 헤비급인지 전혀 모른다.) –
이 준비된 문을 캐시에 저장하지 않으면 모든 로그에 경고 메시지'이미 준비된 쿼리를 다시 준비 중입니다. 동일한 검색어를 두 번 이상 준비하는 것은 일반적으로 반 패턴이며 실적에 영향을 미칠 수 있습니다. 진술을 한 번만 준비해보십시오 .' datastax java driver에서. 여기에 [질문] (http://stackoverflow.com/questions/22915840/re-using-preparedstatement-when-using-datastax-cassandra-driver)이 더 자세히 설명되어 있으므로 준비된 문장을 다시 사용하기로 결정했습니다. . – john