美文网首页
通过CompletableFuture控制线程间的依赖关系

通过CompletableFuture控制线程间的依赖关系

作者: 砌月东谷 | 来源:发表于2021-06-28 07:26 被阅读0次

    Future接口可以创建出新的线程,并在新线程中执行异步操作,但是,如果使用Future接口创建了多个线程,那么这些线程各自执行,不存在依赖关系,并且无法控制各个线程的执行步骤,为了解决这个问题,JDK8开始引入了了Future新的实现类CompletableFuture.

    CompletableFuture不但可以创建出异步执行的线程,还可以控制线程的执行步骤,并且可以监控所有线程的结束时刻,例如,可以使用CompletableFuture创建A和B两个线程,然后规定A,B线程各需要执行3个不同的阶段,并且当A,B全部执行完毕后(或任意一个执行完毕后),再触发某个方法

    CompletableFuture提供了四个异步执行任务的方法:

    [图片上传失败...(imag image-20210628064939775.png

    e-6da60a-1624836327362)]

    其中,supplyAsync()用于有返回值的任务,runAsync则用于没有返回值的任务,Executor默认使用ForkJoinPool.commonPool()创建的线程池,除了这些用于执行线程任务的方法外,CompletableFuture还提供了多线程执行时的两种逻辑:

    allof()方法会一直阻塞,直到线程池Executor中的所有线程全部执行完毕

    anyof()方法会一直阻塞,直到线程池Executor中有任何一个线程执行完毕

    范例:

    有1,2,3,4四个数字,现要求创建4个线程对这些数字进行处理,并要求每个线程必须安装以下步骤执行

    1. 对4个数字值各自加上64,使之转为A,B,C,D对应的ASCII值

    2. 将ASCII值转为对应的A,B,C,D字符

    3. 将转后的A,B,C,D加入一个集合中,

    4. 当4个线程全部执行完毕后,打印出转换后的结果集

    import java.util.List;
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class CompletableFutureDemo {
     public static void main(String[] args) {
     //原始数据集
     CopyOnWriteArrayList<Integer> taskList = new CopyOnWriteArrayList();
     taskList.add(1);
     taskList.add(2);
     taskList.add(3);
     taskList.add(4);
    
     // 结果集
     List<Character> resultList = new ArrayList<>();
     //线程池,可容纳四个线程
     ExecutorService executorService = Executors.newFixedThreadPool(4);
    
     CompletableFuture[] cfs = taskList.stream()
     //第一阶段
     .map(integer -> CompletableFuture.supplyAsync(
     () -> calcASCII(integer), executorService)
     //第二阶段
     .thenApply(i -> {
     char c = (char) (i.intValue());
     System.out.println("【阶段2】线程"
     + Thread.currentThread().getName() + "执行完毕,"
     + "已将int"
     + i + "转为了字符" + c);
     return c;
     })
     //第三阶段
     .whenComplete((ch, e) -> {
     resultList.add(ch);
     System.out.println("【阶段3】线程" +
     Thread.currentThread().getName() + "执行完毕," + "已将"
     + ch + "增加到了结果集" + resultList + "中");
     executorService.shutdown();
     })
     ).toArray(CompletableFuture[]::new);
    
     // 封装后无返回值,必须自己whenComplete()获取
     CompletableFuture.allOf(cfs).join();//future.get()
    
     System.out.println("完成!result=" + resultList);
     }
    
     //计算i的ASCII值
     public static Integer calcASCII(Integer i) {
     try {
     if (i == 1) {
     Thread.sleep(5000);
     } else {
     Thread.sleep(1000);
     }
     //数字 -> A-D对应的ascii
     i = i + 64;
     System.out.println("【阶段1】线程" + Thread.currentThread().getName()
     + "执行完毕," + "已将" + i
     + "转为了A(或B或C或D)对应的ASCII" + i);
     } catch (InterruptedException e) {
     e.printStackTrace();
     }
     return i;
     }
    }
    </pre>
    

    相关文章

      网友评论

          本文标题:通过CompletableFuture控制线程间的依赖关系

          本文链接:https://www.haomeiwen.com/subject/jxofultx.html