如何在Java中发送异步请求并收集响应

如何在Java中发送异步请求并收集响应,java,asynchronous,rx-java,Java,Asynchronous,Rx Java,我有一个列表,比如说2000个用户id,我想向同一台服务器发送异步请求,将id作为参数传递给WebTarget 系统将返回映射到类UserReport的JSON。它包括一个列表,大小为1(如果找到用户) 对于每个结果,我都希望将用户保存在数据库中。有没有一种方法可以使它完全异步?i、 e一旦收到响应,立即向数据库发送插入 发送单个请求的我的代码: public UserReport runRequest(String id){ return this.webTarget.path("so

我有一个列表,比如说2000个用户id,我想向同一台服务器发送异步请求,将id作为参数传递给
WebTarget

系统将返回映射到类UserReport的JSON。它包括一个
列表
,大小为1(如果找到用户)

对于每个结果,我都希望将用户保存在数据库中。有没有一种方法可以使它完全异步?i、 e一旦收到响应,立即向数据库发送插入

发送单个请求的我的代码:

public UserReport runRequest(String id){
    return this.webTarget.path("some_path")
            .queryParam("id", id)
            .request(MediaType.TEXT_PLAIN_TYPE)
            .get(new GenericType<UserReport >() {});
}
public UserReport runRequest(字符串id){
返回此.webTarget.path(“某些路径”)
.queryParam(“id”,id)
.request(MediaType.TEXT\u PLAIN\u类型)
.get(新的GenericType(){});
}
最后一个问题。。使用可观察或未来?

首先,大小为0或1的
列表可以更改为
可选

您可以使用
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;
}
公共类Q43912265{
静态随机=新随机();
公共静态void main(字符串[]args){
可观测范围(11000)
.map(字符串::valueOf)
.flatMap(id->
可观察。仅(id)
.observeOn(Schedulers.io())
.map(Q43912265::runRequest))
.filter(ur->ur.getUser().isPresent())
.doOnNext(Q43912265::插入)
.subscribe();
}
@Skillythrows(InterruptedException.class)
静态UserReport runRequest(字符串id){
System.out.printf(“请求%s在%s上\n”,id,Thread.currentThread());
Thread.sleep(random.nextInt(1000));
System.out.printf(“在%s上完成%s\n”,id,Thread.currentThread());
返回新用户报告(id,可选.ofNullable(random.nextDouble()>0.7?null:新用户(random.nextInt()));
}
静态void插入(UserReport-ur){
System.err.printf(“在%s上插入%s\n”,ur,Thread.currentThread());
}
}
@价值观
类用户报告{
字符串id;
可选用户;
}
@价值观
类用户{
int-id;
}
请注意,如果您直接运行上面的代码,它将在所有任务完成之前终止。让它阻塞

在这种情况下,您可以更改具有有限线程的调度程序,或者
io
调度程序将创建大约1000个线程。

首先,大小为0或1的
列表
可以更改为
可选

您可以使用
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;
}
公共类Q43912265{
静态随机=新随机();
公共静态void main(字符串[]args){
可观测范围(11000)
.map(字符串::valueOf)
.flatMap(id->
可观察。仅(id)
.observeOn(Schedulers.io())
.map(Q43912265::runRequest))
.filter(ur->ur.getUser().isPresent())
.doOnNext(Q43912265::插入)
.subscribe();
}
@Skillythrows(InterruptedException.class)
静态UserReport runRequest(字符串id){
System.out.printf(“请求%s在%s上\n”,id,Thread.currentThread());
Thread.sleep(random.nextInt(1000));
System.out.printf(“在%s上完成%s\n”,id,Thread.currentThread());
返回新用户报告(id,可选.ofNullable(random.nextDouble()>0.7?null:新用户(random.nextInt()));
}
静态void插入(UserReport-ur){
System.err.printf(“在%s上插入%s\n”,ur,Thread.currentThread());
}
}
@价值观
类用户报告{
字符串id;
可选用户;
}
@价值观
类用户{
int-id;
}
请注意,如果您直接运行上面的代码,它将在所有任务完成之前终止。让它阻塞


在这种情况下,您可以更改具有有限线程的调度程序,或者
io
调度程序将创建大约1000个线程。

我最终使用
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;
}
public List getAllUsers(列表ID){
列表期货=新的ArrayList();
ExecutorService executor=Executors.newFixedThreadPool(10);
int counterU=0;
用于(字符串id:ids){
可调用任务=()->{
返回runRequest(id);
};
添加(执行者提交(任务));
info(“为UserId{}添加了任务{}.”,counterH++,id);
}
List toReturn=new ArrayList();
for(未来:未来){
试一试{
UserReport=future.get();
if(report.getUsers()!=null){
User temp=report.getUsers().get(0);
info(“获取了用户{}的详细信息,temp.getId());
返回。添加(临时);
插入器TODB(温度);
}
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(执行例外){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
executor.shutdown();
回归回归;
}

我终于用
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;
}
public List getAllUsers(列表ID){
列表期货=新的ArrayList();
ExecutorService executor=Executors.newFixedThreadPool(10);
int counterU=0;
用于(字符串id:ids){
可调用任务=()->{
返回runRequest(id);
};
添加(执行者提交(任务));
info(“为UserId{}添加了任务{}.”,counterH++,id);
}
List toReturn=new ArrayList();
for(未来:未来){
试一试{
UserReport=future.get();
if(report.getUsers()!=null){
User temp=report.getUsers().get(0);
info(“获取了用户{}的详细信息,temp.getId());
返回。添加(临时);
插入器TODB(温度);
}
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(执行)