java - 如何让 ExecutorService 中的线程进入等待阶段

标签 java multithreading spring-boot java-stream executorservice

在我的 Web 应用程序中,我需要在一次 API 调用中调用大约 10 多个方法。为了提高效率,我使用 ExecutorService同时创建多个线程。每个方法返回不同的对象期望 fav_a(), fav_b(), fav_c() . (为方便起见,下面给出了示例代码)

@GetMapping(RequestUrl.INIT)
public ResponseEntity<Map<String, List<?>>> init() throws ExecutionException, InterruptedException {

    ExecutorService service = Executors.newFixedThreadPool(6);

    Future<List<Object>> method_a = service.submit(() -> someService.method_a());
    Future<List<Object>> method_b = service.submit(() -> someService.method_b());
    Future<List<Object>> method_c = service.submit(() -> someService.method_c());       
    
    Future<List<FavouriteConverter>> fav_a = service.submit(() -> someService.fav_a());
    Future<List<FavouriteConverter>> fav_b = service.submit(() -> someService.fav_b());
    Future<List<FavouriteConverter>> fav_c = service.submit(() -> someService.fav_c());

    service.shutdown();

    List<FavouriteConverter> combinedFavourite = Stream.of(fav_a.get(), fav_b.get(), fav_c.get()).flatMap(f -> f.stream()).collect(Collectors.toList());
    combinedFavourite=combinedFavourite.stream()
            .sorted(Comparator.comparing(FavouriteConverter::get_id, Comparator.reverseOrder()))
            .limit(25)
            .collect(Collectors.toList());

    Map<String, List<?>> map = new HashMap<>();    

    map.put("method_a", method_a.get());
    map.put("method_b", method_b.get());
    map.put("method_c", method_c.get());
    map.put("favourite", combinedFavourite);

    return new ResponseEntity<>(map, HttpStatus.OK);

}
首先我需要得到 fav_a.get(), fav_b.get(), fav_c.get()使 combinedFavourite .如果其中任何一个延迟,逻辑将是错误的。创建线程是昂贵的。
  • 是否Stream自动处理这种情况?
  • fav_a(), fav_b(), fav_c()比其他方法更早地完成工作,我该如何放置 combinedFavourite进入另一个线程?这意味着如何制作Future<List<FavouriteConverter>> combinedFavourite在等待阶段直到fav_a.get(), fav_b.get(), fav_c.get()完成。 (假设 method_a(),method_b(),method_c() 仍在运行。)
  • 最佳答案

  • 不,Streams 不负责加入这些线程。
  • 由于您等待这 3 个线程的结果并将它们放入返回的映射中,因此只要您必须等待并返回结果,将此类逻辑包装在单独的线程中对您没有帮助。
    使用 ExecutorService::invokeAll 执行所有任务并在所有任务完成时返回 Futures 列表(当 Future::donetrue 时)。
    List<Future<List<Object>>> list = service.invokeAll(
        Arrays.asList(
            () -> someService.method_a(),
            () -> someService.method_b(),
            () -> someService.method_c()
    ));
    
    请注意,这些是有保证的:
  • 结果List<Future>与给定的任务集合的顺序相同(根据其 Iterator )。
  • 如果池中的线程数大于或等于已执行的任务(假设没有其他任务使用同一线程池中的线程),则所有任务都将在单独的线程中运行。


  • 此逻辑可帮助您处理完整的结果。

    关于java - 如何让 ExecutorService 中的线程进入等待阶段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63067126/

    相关文章:

    java - Spring Boot中自动调用应用程序的默认网页

    java - SQLite 连接和资源,良好实践

    Java线程从同一目录加载多个文件

    java - 映射到没有 servlet 映射记录的 servlet

    Spring Boot + Jetty & 热部署

    Spring-boot jpa如何找到具有最大值的实体

    java - 距离公式错误

    c# - Object Disposed异常与多线程应用

    multithreading - 并行编码与多线程(在单个CPU上)

    C++线程和无限循环