我有一个允许说2000用户id的列表,我想将异步请求发送到同一个服务器,将id作为参数传递给WebTarget
。
系统将返回映射到UserReport类的JSON。它包含List<User>
,大小为1(如果找到用户)。
对于每个结果,我想将用户保存在DataBase中。有没有办法让它全部异步?即只要我收到回复,就会向数据库发送一个INSERT。
我发送单个请求的代码:
public UserReport runRequest(String id){
return this.webTarget.path("some_path")
.queryParam("id", id)
.request(MediaType.TEXT_PLAIN_TYPE)
.get(new GenericType<UserReport >() {});
}
最后一个问题..使用Observable还是Future?
答案 0 :(得分:0)
首先,大小为0或1的List<User>
可以更改为Optional<User>
。
您可以使用flatMap
来调度异步任务。这是我的代码。
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;
}
请注意,如果您直接运行上面的代码,它将在所有任务完成之前终止。使其阻止。
在这种情况下,您可以使用有限的线程更改调度程序,或io
调度程序将创建大约1000个线程。
答案 1 :(得分:0)
我终于使用ExecutorService
和Future
我发布了答案:
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;
}