posts

Thread-CompletableFuture-Test

Java 多线程与 CompletableFuture 异步编程的测试代码合集。

Thread

public class CompletableFutureDemo {
  long st = System.currentTimeMillis();

  /**
* 全流式处理转换成CompletableFuture[]+allOf组装成一个无返回值CompletableFuture,join等待执行完毕。返回结果whenComplete获取
*/
  @Test
  public void CompletableFutureTest() {
    // 结果集
    List<String> result = new ArrayList<>();
    // 需要处理的数据集 10个线程,每个线程处理一个str
    List<String> lists = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
    //定长10线程池
    ExecutorService exs = Executors.newFixedThreadPool(10);
    CompletableFuture[] cfs = lists.stream().map(str -> CompletableFuture.supplyAsync(() -> calc(str), exs)
                         //thenAccept只接受不返回不影响结果
                         .thenApply("final-"::concat)
                         //获取任务完成先后顺序
                         .whenComplete((v, e) -> {
                          System.out.println("任务" + v + "完成!result=" + v + ",异常 e=" + e + "," + new Date());
                                                   result.add(v);
                                                 })).toArray(CompletableFuture[]::new);
    //等待总任务完成,但是封装后无返回值,必须自己whenComplete()获取
    CompletableFuture.allOf(cfs).join();
    System.out.println("任务完成先后顺序,结果list2=" + result + ",耗时=" + (System.currentTimeMillis() - st));
    exs.shutdown();
    Assert.assertTrue(CollUtil.isNotEmpty(result));
  }

  /**
* 循环创建CompletableFuture list,组装返回一个有返回值的CompletableFuture,返回结果get()获取
*/
  @Test
  public void CompletableFutureTest2() {
    // 结果集
    List<String> result;
    // 需要处理的数据集 10个线程,每个线程处理一个str
    List<String> lists = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
    //定长10线程池
    ExecutorService exs = Executors.newFixedThreadPool(10);
    List<CompletableFuture<String>> futureList = new ArrayList<>();
    try {
      for (String str : lists) {
        //异步执行
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> calc(str), exs)
          //thenAccept只接受不返回不影响结果
          .thenApply("final-"::concat)
          //如需获取任务完成先后顺序,此处代码即可
          .whenComplete((v, e) ->
                        System.out.println("任务" + v + "完成!result=" + v + ",异常 e=" + e + "," + new Date()));
        futureList.add(future);
      }
      //1.构造一个空CompletableFuture,子任务数为入参任务list size
      CompletableFuture<Void> allDoneFuture = CompletableFuture
        .allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
      //2.流式(总任务完成后,每个子任务join取结果,后转换为list)
      result = allDoneFuture.thenApply(v -> futureList.stream().map(CompletableFuture::join)
                                       .collect(Collectors.toList())).get();
      System.out.println("任务完成先后顺序,结果list2=" + result + ",耗时=" + (System.currentTimeMillis() - st));
      Assert.assertTrue(CollUtil.isNotEmpty(result));
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    } finally {
      exs.shutdown();
    }

  }

  private String calc(String str) {
    try {
      if (str.equals("a")) {
        Thread.sleep(3000);
      } else if (str.equals("b")) {
        Thread.sleep(5000);
      } else {
        Thread.sleep(1000);
      }
      str = str.concat("_").concat(Thread.currentThread().getName());
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return str;
  }
}