2017-08-29 2 views
-1

Ich habe versucht, asynchrone Abfrage mit java-driver-async-queries zu implementieren. Ich ändere eine Liste in der FutureCallback, aber es scheint, dass es nicht funktioniert -Sammlung mit ResultSetFuture ändern

Gibt es einen anderen Weg?

Basierend auf Mikhail Bakscheev Antwort ich implementiert und jetzt bekommen richtige Ergebnis. Nur eine Wendung. Es gibt einige zusätzliche Logik, die ich implementieren muss. Ich frage mich, ob ich List<MyClass> statt List<ResultSetFuture> und MyClass als verwenden können -

public class MyClass { 

    private Integer   productCount; 
    private Integer   stockCount; 
    private ResultSetFuture result; 
} 

Dann, während das Iterieren FutureList gesetzt, wie -

ResultSetFuture result = session.executeAsync(query, key.get()); 
MyClass allResult = new MyClass(); 
allResult.setInCount(inCount); 
allResult.setResult(result); 
allResult.setSohCount(values.size() - inCount); 

futuresList.add(allResult); 
+0

Was ist die Definition von „nicht funktioniert“ implementieren sollte? Veröffentlichen Sie das erwartete Verhalten und das tatsächliche Verhalten. –

+1

Sie warten nicht auf Ihre Zukunft, oder? Es sieht so aus, als würdest du eine Menge Futures erschaffen und die Ergebnisstruktur sofort ausdrucken. Die Ergebnisstruktur wurde nicht ausgefüllt, da sich die meisten Futures noch im Flug befinden. – RussS

+0

Danke. Was ist die Korrektur? Gibt es ein Codebeispiel, auf das ich verweisen kann? – Saurabh

Antwort

1

Wie @RussS erwähnt, wird der Code nicht alle Futures warten abgeschlossen .

Es gibt viele Möglichkeiten, den asynchronen Code zu synchronisieren. Zum Beispiel mit CountDownLatch:

EDIT: Auch separte Thread für Rückrufe und verwenden gleichzeitige Sammlung für Produkte verwenden, bitte.

ConcurrentLinkedQueue<Product> products = new ConcurrentLinkedQueue<Product>(); 
final Executor callbackExecutor = Executors.newSingleThreadExecutor(); 
final CountDownLatch doneSignal = new CountDownLatch(/*the Map size*/); 
for (// iterating over a Map) { 
    key = entry.getKey(); 
    String query = "SELECT id,desc,category FROM products where id=?"; 
    ResultSetFuture future = session.executeAsync(query, key); 
    Futures.addCallback(future, 
     new FutureCallback<ResultSet>() { 
      @Override public void onSuccess(ResultSet result) { 
       Row row = result.one(); 
       if (row != null) { 
        Product product = new Product(); 
        product.setId(row.getString("id")); 
        product.setDesc(row.getString("desc")); 
        product.setCategory(row.getString("category")); 

        products.add(product); 
       } 
       doneSignal.countDown(); 

      } 

      @Override public void onFailure(Throwable t) { 
       // log error 
       doneSignal.countDown(); 
      } 
     }, 
     callbackExecutor 
    ); 
} 

doneSignal.await();   // wait for all async requests to finish 
System.out.println("Product List : " + products); 

Eine andere Möglichkeit ist es, alle Futures in einer Liste zu sammeln und alle Ergebnisse als eine einzige Zukunft mit Guave des Futures.allAsList warten, zB:

List<ResultSetFuture> futuresList = new ArrayList<>(/*Map size*/); 
     for (/* iterating over a Map*/) { 
      key = entry.getKey(); 
      String query = "SELECT id,desc,category FROM products where id=?"; 
      futuresList.add(session.executeAsync(query, key)); 
     } 

     ListenableFuture<List<ResultSet>> allFuturesResult = Futures.allAsList(futuresList); 
     List<Product> products = new ArrayList<>(); 
     try { 
      final List<ResultSet> resultSets = allFuturesResult.get(); 
      for (ResultSet rs : resultSets) { 
       if (null != rs) { 
        Row row = rs.one(); 
        if (row != null) { 
         Product product = new Product(); 
         product.setId(row.getString("id")); 
         product.setDesc(row.getString("desc")); 
         product.setCategory(row.getString("category")); 

         products.add(product); 
        } 
       } 
      } 
     } catch (InterruptedException | ExecutionException e) { 
      System.out.println(e); 
     } 
     System.out.println("Product List : " + products); 

EDIT 2

Ich frage mich, ob ich List anstelle von List und MyClass als

verwenden kann ja

Technisch gesehen, aber man kann nicht List<MyClass> in Futures.allAsList in diesem Fall passieren oder MyClassListenableFuture Schnittstelle

+0

Danke. Ich hatte ein Problem mit verschachtelten Abfragen in Cassandra und folgte Ihrer Antwort https://StackOverflow.com/questions/45471519/improve-performance-in-cassandra-and-java-collections. Jetzt kommt ein zeitweiliges Problem, wenn meine Produkte irgendwann leer werden. Aber wenn ich die Liste innerhalb onSuccess-Methode drucke, gibt es mir Ergebnis. Wenn ich wait() verwende, dauert die Methode lange. Bitte vorschlagen. – Saurabh

+0

@Saurabh, ich habe meine Antwort verbessert –

+0

Ich habe meine Frage bearbeitet. Bitte guck dir das an. – Saurabh

Verwandte Themen