2016-09-29 2 views
2

Débutant du fil ici. J'ai besoin d'une action Struts pour récupérer des données en appelant un service web plusieurs fois avec une requête différente à chaque fois, et j'attends que chaque requête soit terminée pour que je puisse afficher le résultat.Comment puis-je faire beaucoup d'appels WS dans des threads séparés et incrémenter une seule variable de résultat?

Donc, fondamentalement, je fais comme ça:

// The list of the region codes used for the requests 
List<String> codesRegions; 

// Init of a variable containing the total amount of data 
Integer totalAmount = 0; 

// For every region 
for(String codeRegion : codesRegions) 
{ 
    MyRegionStub stub = createRegionStub(); 

    // Call of the WS with the code region 
    MyRegionRequest request = new MyRegionRequest(); 
    request.setCodeRegion(codeRegion); 

    // Getting the number associated to the region and incrementing totalAmount 
    MyRegionResponse response = stub.getRegionStats(request); 
    totalAmount += response.getRegionStats(); 
} 

// Once all the calls are done, I display the result 
request.setAttribute("totalAmount", totalAmount); 
mapping.findForward("success"); 

Mon problème est que je reçois souvent des erreurs délai d'attente en faisant ce que je fais appel de cette WS un grand nombre de fois. Donc, je veux savoir comment je peux faire chaque appel dans un fil séparé, et incrémenter la même variable de résultat sans aucune erreur.

Une autre chose que je veux savoir, j'ai besoin d'attendre que tous les appels soient complétés pour afficher les données. Que dois-je faire pour appeler mapping.findForward("success"); seulement quand c'est fini?

Répondre

1

Si vous utilisez java 8 Je recommande CompletableFuture

Cela vous permettra de créer une charge de threads qui exécutent async quelque chose comme ça

CompleteableFuture<Integer> future CompleteableFuture.supplyAsync(getRegionStats(codeRegion)) 

Une fois que vous avez créé tous les contrats à terme, vous pouvez ensuite vérifier quand ils sont tous terminés.

CompleteableFuture.allOf(future1, future2).join(); 

Ensuite, pour chacun de vos futures que vous pouvez faire additionner les valeurs

for(CompleteableFuture future : futures) 
     totalAmount+= future.get() 
+0

Merci beaucoup pour votre réponse. Malheureusement, je travaille sur un vieux projet en utilisant une ancienne version de Java (Java 6) donc je ne peux pas utiliser cette solution ... Je vais le garder à l'esprit pour des buts plus tardifs! – Someday

0

Vous pouvez utiliser Executor framework avec CountDownLatch pour cela. ExecutorService exécutera des tâches asynchrones dans le pool de threads et CountDownLatch attendra l'achèvement de toutes les tâches.

Dans ce cas, vous devez noter que countDownLatch.countDown(); doit être présent dans le bloc finally afin qu'il soit garanti d'être exécuté, et pour le montant total, vous devez utiliser le filetage sécurisé AtomicInteger.

Votre code ressemblera à ceci:

ExecutorService threadPool = Executors.newFixedThreadPool(10); 
CountDownLatch countDownLatch = new CountDownLatch(codesRegions.size()); 
AtomicInteger totalAmount = new AtomicInteger(0); 

for (String codeRegion : codesRegions) 
{ 
    threadPool.execute(new Runnable() { 

     @Override 
     public void run() 
     { 
      try 
      { 
       MyRegionStub stub = createRegionStub(); 

       // Call of the WS with the code region 
       MyRegionRequest request = new MyRegionRequest(); 
       request.setCodeRegion(codeRegion); 

       // Getting the number associated to the region and 
       // incrementing 
       // totalAmount 
       MyRegionResponse response = stub.getRegionStats(request); 
       totalAmount.addAndGet(response.getRegionStats()); 
      } 
      finally 
      { 
       countDownLatch.countDown(); 
      } 
     } 
    }); 
} 
try 
{ 
    countDownLatch.await(); 
} 
catch (InterruptedException e) 
{ 
    //Return ERROR in case of current thread is interrupted. 
} 
// Once all the calls are done, I display the result 
request.setAttribute("totalAmount", totalAmount); 
mapping.findForward("success");