有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在单独的线程中执行大量WS调用并增加单个结果变量?

线程初学者在这里

在Struts操作中,我需要通过多次调用Web服务来检索一些数据,每次调用不同的请求,并等待每个请求完成,以便显示结果

所以基本上我是这样做的:

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


共 (2) 个答案

  1. # 1 楼答案

    您可以将Executor frameworkCountDownLatch一起使用。 ExecutorService将在线程池中执行异步任务,CountDownLatch将等待所有任务完成

    在这种情况下,您应该注意countDownLatch.countDown();必须出现在finally块中,这样它就可以保证被执行,并且对于总数量,您应该使用线程安全的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");
    
  2. # 2 楼答案

    如果您使用的是java 8,我建议CompletableFuture

    这将允许您创建一个运行异步的线程负载,比如

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

    一旦你创建了所有的未来,你就可以检查它们何时全部完成

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

    然后,对于你的每一个未来,你可以做价值总和

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