如何将并行进程同步到Web服务?

时间:2015-10-15 11:56:48

标签: java multithreading web-services java-ee

我需要使用Tomcat 7托管的CXF 3开发Web服务操作。我们的模型层是Spring 3。 此操作调用远程服务器托管的16个其他Web服务。我们需要等待所有响应,以构建我们自己的操作的响应。 我们目前按顺序调用每个远程操作。当然,我们有响应时间问题。我认为我们应该并行操作内部调用并同步不同的响应。

什么样的多线程实现可以安全?我们可以做些什么来改善它?

2 个答案:

答案 0 :(得分:1)

我在Future中使用Java的通用@Async和Spring的@Service方法。

简而言之,您按顺序调用服务并将所有结果作为Future s,然后您只需检查所有期货是否已完成处理。如果存在这种可能性,您也可以使用部分数据进行一些工作。

以下是关于如何操作的a simple example。来自链接的示例服务:

@Service
public class GitHubLookupService {

    RestTemplate restTemplate = new RestTemplate();

    @Async
    public Future<User> findUser(String user) throws InterruptedException {
        System.out.println("Looking up " + user);
        User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
        // Artificial delay of 1s for demonstration purposes
        Thread.sleep(1000L);
        return new AsyncResult<User>(results);
    }

}

使用它的方法:

@Override
public void run(String... args) throws Exception {
    // Start the clock
    long start = System.currentTimeMillis();

    // Kick of multiple, asynchronous lookups
    Future<User> page1 = gitHubLookupService.findUser("PivotalSoftware");
    Future<User> page2 = gitHubLookupService.findUser("CloudFoundry");
    Future<User> page3 = gitHubLookupService.findUser("Spring-Projects");

    // Wait until they are all done
    while (!(page1.isDone() && page2.isDone() && page3.isDone())) {
        Thread.sleep(10); //10-millisecond pause between each check
    }

    // Print results, including elapsed time
    System.out.println("Elapsed time: " + (System.currentTimeMillis() - start));
    System.out.println(page1.get());
    System.out.println(page2.get());
    System.out.println(page3.get());
}

答案 1 :(得分:0)

我会使用传统方法使用join()等待线程完成而不是轮询(我不喜欢轮询模式太多)。

对于要复制的通用线程的类型:

public class ThreadedWebServiceRetrieval extends Thread {

    private List<ResultObject> resultList;
    private GenericWebServiceStub stub;

    public ThreadedWebServiceRetrieval (List<ResultObject> resultList, GenericWebServiceStub stub) {
        this.resultList = resultList;
        this.stub = stub;
    }

    public void run() {
        resultList.add(stub.retrieveData());
    }
}

这是并行检索代码:

// ... Controller/Service stuff

List<ResultObject> resultList = new LinkedList<>();//Diamond operator
List<Thread> webServiceList = new LinkedList<>();

webServiceList.add(new ThreadedWebServiceRetrieval(resultList, stub1));
//...
webServiceList.add(new ThreadedWebServiceRetrieval(resultList, stubN));

for (Thread thread : webServiceList) {
    thread.start();
}
for (Thread thread : webServiceList) {
    thread.join();
}

// resultList is fulfilled

这种方法的时间应该是+/-最长的检索。 我使代码非常通用(整体在Thread实现中),但它适合大多数情况。

享受!