Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Cassandra-使用带ListenableFuture的PreparedStatement_Java_Cassandra - Fatal编程技术网

Java Cassandra-使用带ListenableFuture的PreparedStatement

Java Cassandra-使用带ListenableFuture的PreparedStatement,java,cassandra,Java,Cassandra,我正在尝试使用ListenableFuture对Cassandra群集进行异步写入,如下所示: private static Cluster cluster = null; private ListeningExecutorService executorService; private PreparedStatement preparedStatement; private Session session = null; ... executorService = MoreExecuto

我正在尝试使用ListenableFuture对Cassandra群集进行异步写入,如下所示:

private static Cluster cluster = null;
private ListeningExecutorService executorService;
private PreparedStatement preparedStatement;
private Session session = null;

... 

executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(POOL_SIZE));
...

public void writeValue(Tuple tuple) {
    ListenableFuture<String> future = executorService.submit(new Callable<String>() {
       @Override
       public String call() throws Exception {
           if(session == null) {
               session = getCluster().connect("dbname");
               preparedStatement = session.prepare(queryString);
           }

           try {
               BoundStatement boundStatement = preparedStatement.bind(tuple values);
               session.execute(boundStatement);
           } catch(Exception exception) {
                // handle exception
           }

           return null;
       }
    });
私有静态集群集群=null;
私人监听执行服务;
私人编制的报表;
私有会话=null;
... 
executorService=MoreExecutors.ListingDecorator(Executors.newFixedThreadPool(池大小));
...
公共void writeValue(元组){
ListenableFuture=executorService.submit(new Callable()){
@凌驾
公共字符串调用()引发异常{
if(会话==null){
session=getCluster().connect(“dbname”);
preparedStatement=session.prepare(查询字符串);
}
试一试{
BoundStatement BoundStatement=preparedStatement.bind(元组值);
session.execute(boundStatement);
}捕获(异常){
//处理异常
}
返回null;
}
});
如果我将“池大小”设置为1,一切正常。
如果我将池大小设置为>1,我会得到如下错误:

private static Cluster cluster = null;
private ListeningExecutorService executorService;
private PreparedStatement preparedStatement;
private Session session = null;

... 

executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(POOL_SIZE));
...

public void writeValue(Tuple tuple) {
    ListenableFuture<String> future = executorService.submit(new Callable<String>() {
       @Override
       public String call() throws Exception {
           if(session == null) {
               session = getCluster().connect("dbname");
               preparedStatement = session.prepare(queryString);
           }

           try {
               BoundStatement boundStatement = preparedStatement.bind(tuple values);
               session.execute(boundStatement);
           } catch(Exception exception) {
                // handle exception
           }

           return null;
       }
    });
原因:com.datastax.driver.core.exceptions.InvalidQueryException:试图执行未知的准备好的查询:0x75c5b41b9f07afa5384a69790503f963。您可能使用了使用其他群集实例创建的PreparedStatement

因此,我将
session
preparedStatement
放入本地变量。然后,我会收到关于
重新准备已准备好的查询的警告…
并且每次都会创建一个新会话

我希望尽可能地重复使用。我做错了什么?我的选择是什么


使这个类成为静态类会有帮助吗?

这里有各种竞争条件,执行不是线程安全的

集群
会话
PreparedStatement
中的每一个都是应用范围内的单例,即,您只需要一个(对于
PreparedStatement
的每个查询一个)

但是,您正在重新创建一个
会话
,并可能多次准备
PreparedStatement

不要。在构造函数或某个只运行一次的位置初始化一次
会话
,同时准备语句。然后在适当的情况下使用
会话
准备语句


使用单线程执行器,一切都像同步一样运行

session.prepare(queryString);
同时。或您在此处使用的
PreparedStatement

BoundStatement boundStatement = preparedStatement.bind(tuple values);
session.execute(boundStatement);
可能与您初始化的不同

preparedStatement = session.prepare(queryString);
甚至在同一执行线程内。或者您可能正试图使用与初始化会话不同的会话执行
PreparedStatement


  • 准备好的语句是绑定在一个会话上还是可用于另一个会话?

    准备好的语句是从特定会话实例派生的。 因此,当您准备一条语句并将其发送到服务器时 将发送到此会话实例关联的群集 有

  • 美国的javadoc

    会话实例是线程安全的,通常只有一个实例是安全的 每个申请都足够了


    这里有各种各样的竞争条件,执行不是线程安全的

    集群
    会话
    PreparedStatement
    中的每一个都是应用范围内的单例,即,您只需要一个(对于
    PreparedStatement
    的每个查询一个)

    但是,您正在重新创建一个
    会话
    ,并可能多次准备
    PreparedStatement

    不要。在构造函数或某个只运行一次的位置初始化一次
    会话
    ,同时准备语句。然后在适当的情况下使用
    会话
    准备语句


    使用单线程执行器,一切都像同步一样运行

    session.prepare(queryString);
    
    同时。或您在此处使用的
    PreparedStatement

    BoundStatement boundStatement = preparedStatement.bind(tuple values);
    session.execute(boundStatement);
    
    可能与您初始化的不同

    preparedStatement = session.prepare(queryString);
    
    甚至在同一执行线程内。或者您可能正试图使用与初始化会话不同的会话执行
    PreparedStatement


  • 准备好的语句是绑定在一个会话上还是可用于另一个会话?

    准备好的语句是从特定会话实例派生的。 因此,当您准备一条语句并将其发送到服务器时 将发送到此会话实例关联的群集 有

  • 美国的javadoc

    会话实例是线程安全的,通常只有一个实例是安全的 每个申请都足够了


    您可能还希望使用驱动程序的异步API。与其调用
    execute
    (这将在查询期间阻塞线程),不如调用
    executeAsync
    ,并在生成的将来注册回调以处理结果

    如果该回调非常昂贵,并且您不想阻止驱动程序的内部I/O线程,那么您可以提供自己的执行器:

    ListenableFuture<ResultSet> future = session.executeAsync(statement);
    Futures.addCallback(future, new FutureCallback<ResultSet>() {
        public void onSuccess(ResultSet rs) { ... }
        public void onFailure(Throwable t) { ... }
      }, 
      executorService);
    
    ListenableFuture=session.executeAsync(语句);
    Futures.addCallback(future,newfuturecallback(){
    成功时公共无效(结果集rs){…}
    失败时公共无效(可丢弃的t){…}
    }, 
    执行人服务);
    

    文档中有一些关于异步编程的提示。

    您可能还想使用驱动程序的异步API。不要调用
    execute
    (这将在查询期间阻塞线程),而是调用
    exe