2016-09-29 23 views
2

初學者在這裏。如何在單獨的線程中執行大量WS調用並增加單個結果變量?

我需要在Struts動作中通過每次調用webservice多次使用不同的請求來檢索一些數據,並等待每個請求完成,以便我可以顯示結果。

所以基本上我在做這樣的:

// 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"); 

我的問題是,我經常這樣做,因爲我調用這個WS很多次得到超時錯誤。所以我想知道如何在一個單獨的線程中完成每個調用,並且不加任何錯誤地增加相同的結果變量。

我想知道的另一件事,我需要等待所有的呼叫完成顯示數據。只有完成此操作後,我需要做什麼才能撥打mapping.findForward("success");

回答

1

如果您使用的是Java 8,我會建議CompletableFuture

這將允許您創建運行異步像這樣的線程的負載

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

一旦你創建了所有的期貨,然後你可以檢查它們什麼時候全部完成。

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

然後爲每個期貨,你可以做的值相加

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

非常感謝您的回答。不幸的是,我正在使用舊版本的Java(Java 6)開發一箇舊項目,所以我不能使用這個解決方案......但我會在後面的目的中記住它! – Someday

0

您可以使用Executor frameworkCountDownLatch這一點。 ExecutorService將在線程池中執行異步任務,並且CountDownLatch將等待所有任務完成。

在這種情況下,您應該注意塊中必須出現countDownLatch.countDown();,因此它將保證執行,並且總金額您應該使用線程安全AtomicInteger

您的代碼將是這樣的:

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"); 
相關問題