[英]How to send Asynchronous Requests in Java and Collect Responses
I have a list of lets say 2000 user ids and i want to send asynchronous requests to the same server passing the id as a parameter to the WebTarget
. 我有一个让我们说2000用户id的列表,我想将异步请求发送到同一个服务器,将id作为参数传递给WebTarget
。
The System will return JSON which is mapped to class UserReport. 系统将返回映射到UserReport类的JSON。 It includes a List<User>
and will be of size 1 (if user was found). 它包含List<User>
,大小为1(如果找到用户)。
For every result i would like to save the user in a DataBase. 对于每个结果,我想将用户保存在DataBase中。 Is there a way to make it all Asynchronous? 有没有办法让它全部异步? ie As soon as i get a response send an INSERT to the Database. 即我得到响应后立即向数据库发送INSERT。
My code to send a single request: 我发送单个请求的代码:
public UserReport runRequest(String id){
return this.webTarget.path("some_path")
.queryParam("id", id)
.request(MediaType.TEXT_PLAIN_TYPE)
.get(new GenericType<UserReport >() {});
}
Last question.. Use Observable or Future? 最后一个问题..使用Observable还是Future?
First, List<User>
with size 0 or 1 can change to Optional<User>
. 首先,大小为0或1的List<User>
可以更改为Optional<User>
。
You can use flatMap
to scheduler async tasks. 您可以使用flatMap
来调度异步任务。 Here is my code. 这是我的代码。
public class Q43912265 {
static Random random = new Random();
public static void main(String[] args) {
Observable.range(1, 1000)
.map(String::valueOf)
.flatMap(id ->
Observable.just(id)
.observeOn(Schedulers.io())
.map(Q43912265::runRequest))
.filter(ur -> ur.getUser().isPresent())
.doOnNext(Q43912265::insert)
.subscribe();
}
@SneakyThrows(InterruptedException.class)
static UserReport runRequest(String id) {
System.out.printf("request %s on %s\n", id, Thread.currentThread());
Thread.sleep(random.nextInt(1000));
System.out.printf("done %s on %s\n", id, Thread.currentThread());
return new UserReport(id, Optional.ofNullable(random.nextDouble() > 0.7 ? null : new User(random.nextInt())));
}
static void insert(UserReport ur) {
System.err.printf("insert %s on %s\n", ur, Thread.currentThread());
}
}
@Value
class UserReport {
String id;
Optional<User> user;
}
@Value
class User {
int id;
}
Note that if you run code above directly, it will terminate before all tasks done. 请注意,如果直接运行上面的代码,它将在所有任务完成之前终止。 To make it blocking. 使它阻止。
And in this case, you can change schedulers with limited thread or io
scheduler will create about 1000 thread. 在这种情况下,您可以使用有限的线程更改调度程序,或者io
调度程序将创建大约1000个线程。
I finally solved it using ExecutorService
and Future
我终于使用ExecutorService
和Future
解决了它
I post the answer: 我发布了答案:
public List<User> getAllUsers(List<String> ids) {
List<Future<UserReport>> futures = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
int counterU = 0;
for (String id : ids) {
Callable<UserReport> task = () -> {
return runRequest(id);
};
futures.add(executor.submit(task));
LOGGER.info("Added Task {} for UserId {}.", counterH++, id);
}
List<User> toReturn = new ArrayList<>();
for (Future<UserReport> future : futures) {
try {
UserReport report = future.get();
if (report.getUsers() != null) {
User temp = report.getUsers().get(0);
LOGGER.info("Got details for User {}.", temp.getId());
toReturn.add(temp);
insertUserToDB(temp);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
executor.shutdown();
return toReturn;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.