我想用相同的方法调用3个Web服务,并且每个结果都将在如下所示的对象中设置:
public Dossie procuraPorCPF(String cpf) {
Dossie dossie = new Dossie();
// first webservice call
dossie.setCnh(detectaClientCnh.verificaCNH(cpf));
// second webservice call
dossie.setFotoCnh(detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
// third webservice call
dossie.setPm(consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
return dossie;
}
在上面的这种情况下,我要调用3个不同的Web服务,每个服务大约需要5秒钟,因此不好继续这段代码。我想知道同时调用这3个Web服务的最佳方法是什么,以及如何使用此代码作为示例来做到这一点。我在这里搜索了一些文章甚至答案,但是我不知道该怎么做。感谢您的耐心等候。
答案 0 :(得分:2)
Java中的并发通过Thread
类进行处理。 Thread
构造函数接受带有Runnable
运行代码的Thread
参数。调用start()
方法时,JVM将创建新线程并执行run()
的{{1}}方法中的代码。
由于Runnable
仅具有单个抽象方法Runnable
,因此您可以使用lambda expression获得更具可读性的代码。我对第一个调用使用传统语法,对其他两个调用使用lambda语法来演示这两种方法。
run()
public Dossie procuraPorCPF(String cpf) {
Dossie dossie = new Dossie();
Thread[] threads = new Thread[3];
threads[0] = new Thread(new Runnable() {
@Override
public void run() {
dossie.setCnh(detectaClientCnh.verificaCNH(cpf));
}
};
threads[0].start();
threads[1] = new Thread(() ->
dossie.setFotoCnh(detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
threads[1].start();
threads[2] = new Thread(() ->
dossie.setPm(consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
threads[2].start();
try {
threads[0].join();
threads[1].join();
threads[2].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return dossie;
}
方法将阻止程序执行,直到调用join()
完成运行为止。通过将Thread
放在方法的末尾,可以保证在返回之前,所有3个请求均已完成。如果这些请求在返回之前是否已完成都没关系,则只需删除join()
,这些请求将在后台运行,而其余的应用程序将运行。
对于大型应用程序,Java还包括thread pools,它将为您管理join()
的创建。由于您的应用程序仅在本地上下文中使用相同的3 Thread
,因此我认为上述解决方案更适合(并且对于此答案更具有教育意义)。
答案 1 :(得分:1)
您可以使用ExecutorService提交Callable并调用Future.get()来检索结果,如下所示(将Future
public Dossie procuraPorCPF(String cpf) {
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<String> cnh = executor.submit(() -> detectaClientCnh.verificaCNH(cpf));
Future<String> fotoCnh = executor.submit(() -> detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
Future<String> pm =
executor.submit(() -> consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
Dossie dossie = new Dossie();
try {
dossie.setCnh(cnh.get());
dossie.setFotoCnh(fotoCnh.get());
dossie.setPm(pm.get());
} catch (InterruptedException | ExecutionException cause) {
cause.printStackTrace();
}
executor.shutdown();
return dossie;
}
答案 2 :(得分:1)
我从晚上开始写这个答案,然后将其留给第二天。到了早上,给出了两个答案,其中一个被OP接受。对于希望查看实施的完整设计和思想而非实际代码的人,请在此处留下答案。
由于Web服务调用需要时间来响应,因此它们被异步调用,这意味着主线程与这些调用不同步。
因此,它们的设计使您可以在单独的线程上进行单独的调用。
对于您而言,重要的Java元素是:
call()
方法中包含Web服务的调用代码。
奖励步骤:在我看来,这三个Web服务调用需要以相同的顺序重复进行(我听不懂语言,因为它不是英语)。对于这样的代码,可以在实现的第1步中创建的类的顶部创建一个单独的Orchestrator类。
此协调器类可以扩展Thread类并进行三个Web服务调用。现在,该类可以异步运行,而不用进行三个Web服务调用。使代码保持模块化并抽象出复杂性。