我们有一个stipes(java)web应用程序,它需要从一个方法调用大约15个不同的webserivce。例如:…
public Resolution userProfile()
{
serviceOneCall();
serviceTwoCall();
serviceThreeCall();
serviceFourCall();
....
serviceTenCall();
return new RedirectResolution("profiel.jsp");
}
所有这些都可以并行调用,并且不相互依赖。大多数这些调用都在做的一件事是将数据放入会话中,其中一两个可能会将数据放入同一个会话中的对象中,因此线程安全可能是一个问题。
有人能提出一个同时调用所有这些的好方法吗?
所有并行完成这项工作的解决方案都将涉及生成新线程或向线程池提交作业,以便进行远程网络调用。
避免线程安全问题的一个好方法是使用executorService
并提交Callable<T>
的子类(到submit(Callable)
或invokeAll(Collection<Callable>)
方法),并让Callables返回响应值。这样,您的初始方法可以简单地处理每个调用的返回值,并选择在会话中设置响应或更新其他对象,而不是在另一个线程中执行此操作。
所以基本算法:
- 将这些调用中的每一个提交给
Callable<T>
子类中的executesService - 收集您从executorService返回的
Future<T>
- 在每个线程上调用
Future.get()
进行阻塞,直到您得到响应,然后在主线程上按照您的意愿处理响应
使用带有线程池的ExecutorService
为需要调用的每个WS提交Callable
s,并在有机会进行并发修改时更新的对象上同步。
您可能想使用Guava的并发扩展来更容易地管理Future
,例如使用Futures.allAsList()
,它将把List<Future<T>>
转换为Future<List<T>>
,因此您只需要执行一个get()
来等待所有答案。
for (i = 0; i <= numOfServiceCalls; i++) {
new Thread(new Runnable() {
switch(i) {
case 1 : serviceOneCall();
break();
case 2 : serviceTwoCall();
break();
// Keep going with as many cases as you have.
}
});
}