【发布时间】:2017-04-23 04:14:36
【问题描述】:
我正在使用 datastax java driver 3.1.0 连接到 cassandra 集群,我的 cassandra 集群版本是 2.0.10。我正在使用 QUORUM 一致性异步编写。
public void save(final String process, final int clientid, final long deviceid) {
String sql = "insert into storage (process, clientid, deviceid) values (?, ?, ?)";
try {
BoundStatement bs = CacheStatement.getInstance().getStatement(sql);
bs.setConsistencyLevel(ConsistencyLevel.QUORUM);
bs.setString(0, process);
bs.setInt(1, clientid);
bs.setLong(2, deviceid);
ResultSetFuture future = session.executeAsync(bs);
Futures.addCallback(future, new FutureCallback<ResultSet>() {
@Override
public void onSuccess(ResultSet result) {
logger.logInfo("successfully written");
}
@Override
public void onFailure(Throwable t) {
logger.logError("error= ", t);
}
}, Executors.newFixedThreadPool(10));
} catch (Exception ex) {
logger.logError("error= ", ex);
}
}
下面是我的CacheStatement类:
public class CacheStatement {
private static final Map<String, PreparedStatement> cache =
new ConcurrentHashMap<>();
private static class Holder {
private static final CacheStatement INSTANCE = new CacheStatement();
}
public static CacheStatement getInstance() {
return Holder.INSTANCE;
}
private CacheStatement() {}
public BoundStatement getStatement(String cql) {
Session session = CassUtils.getInstance().getSession();
PreparedStatement ps = cache.get(cql);
// no statement cached, create one and cache it now.
if (ps == null) {
synchronized (this) {
ps = cache.get(cql);
if (ps == null) {
cache.put(cql, session.prepare(cql));
}
}
}
return ps.bind();
}
}
我上面的save 方法将从多个线程调用,我认为BoundStatement 不是线程安全的。顺便说一句,StatementCache 类是线程安全的,如上所示。
- 因为
BoundStatement不是线程安全的。如果我从多个线程异步编写,我上面的代码会有什么问题吗? - 其次,我在
addCallback参数中使用了Executors.newFixedThreadPool(10)。这样可以吗还是会有什么问题?或者我应该使用MoreExecutors.directExecutor。那么这两者有什么区别呢?最好的方法是什么?
以下是我使用 datastax java 驱动程序连接到 cassandra 的连接设置:
Builder builder = Cluster.builder();
cluster =
builder
.addContactPoints(servers.toArray(new String[servers.size()]))
.withRetryPolicy(new LoggingRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE))
.withPoolingOptions(poolingOptions)
.withReconnectionPolicy(new ConstantReconnectionPolicy(100L))
.withLoadBalancingPolicy(
DCAwareRoundRobinPolicy
.builder()
.withLocalDc(
!TestUtils.isProd() ? "DC2" : TestUtils.getCurrentLocation()
.get().name().toLowerCase()).withUsedHostsPerRemoteDc(3).build())
.withCredentials(username, password).build();
【问题讨论】:
-
您每次调用 save 时都会创建一个新的线程池,而是创建线程池的静态或实例版本并重用它。
-
是的,我在阅读以下答案后做到了。我已经在类的顶部将它声明为 final 然后使用它。一般来说,
MoreExecutors.directExecutor()和threadpool之间有什么区别? -
@ChrisLohfink 在回调中使用
MoreExecutors.directExecutor()和threadpool有什么真正的好处吗?你能帮我理解一下吗?
标签: java multithreading cassandra datastax-java-driver