2022.8.21 Forkjoin与异步回调

14、Forkjoin(分支合并)

什么是 ForkJoin

ForkJoin 在 JDK 1.7 , 并行执行任务!提高效率。在大数据量中!

大数据:Map Reduce (把大任务拆分为小任务)

Forkjoin 特点:工作窃取,这里面维护的是双端队列

接口

通过forkjoinPool来执行forkjoin

构造方法

使用forkjoin

 1  package com.xing.forkjoin;
 2  3  import java.util.concurrent.RecursiveTask;
 4  5  /**
 6   * 求和计算的任务
 7   * 3000 6000(frokjoin) 9000(Stream并行流)
 8   * 如何使用frokjoin
 9   * 1.forkjoinPool通过它来执行
10   * 2.计算任务forkjoinPool.execute(ForkJoinTask task)
11   * 3.计算类要继承RecursiveTask(递归任务有返回值)
12   */
13  //                                       重写方法的返回值类型
14  public class ForkJoinDemo extends RecursiveTask<Long> {
15      private Long start;
16      private Long end;
17      //临界值
18      private Long temp = 10000L;
19 20      public ForkJoinDemo(Long start, Long end) {
21          this.start = start;
22          this.end = end;
23      }
24 25      //重写的方法
26      @Override
27      protected Long compute() {
28          //正常计算
29          if((end-start) < temp){
30              Long sum = 0L;
31              for (long i = start; i <= end; i++) {
32 33                  sum += i;
34              }
35              return sum;
36          }else {
37              //forkjoin 递归
38              long middle = (start + end) / 2; //中间值
39 40              // 将一个任务拆分成两个任务
41              ForkJoinDemo task1 = new ForkJoinDemo(start,middle);
42              task1.fork();//拆分任务,把任务压入线程队列
43 44              ForkJoinDemo task2 = new ForkJoinDemo(middle,end);
45              task2.fork();
46 47              //返回结果
48              return task1.join() + task2.join();
49 50          }
51      }
52  }
53

不同方法的执行速度 package com.xing.forkjoin;

 1  import java.util.concurrent.ExecutionException;
 2  import java.util.concurrent.ForkJoinPool;
 3  import java.util.concurrent.ForkJoinTask;
 4  import java.util.stream.LongStream;
 5  6  public class Test {
 7      public static void main(String[] args) {
 8          test1();
 9          try {
10              test2();
11          } catch (ExecutionException e) {
12              e.printStackTrace();
13          } catch (InterruptedException e) {
14              e.printStackTrace();
15          }
16          test3();
17      }
18      //普通程序员
19      public static void test1(){
20          Long sum = 0L;
21          long start = System.currentTimeMillis();
22          for (long i = 1L; i <= 10_0000_0000; i++) {
23              sum += i;
24          }
25          long end = System.currentTimeMillis();
26          System.out.println("sum = " + sum + "时间:" + (end - start));
27      }
28      //使用forkjoin
29      public static void test2() throws ExecutionException, InterruptedException {
30          long start = System.currentTimeMillis();
31 32          ForkJoinPool forkJoinPool = new ForkJoinPool();
33          ForkJoinTask<Long> task = new ForkJoinDemo(0L,10_0000_0000L); //向下转型
34 35          ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务
36          Long sum = submit.get();//获得结果
37 38 39          long end = System.currentTimeMillis();
40          System.out.println("sum=" + sum +"时间:" + (end - start));
41      }
42      //用Stream并行流
43      public static void test3(){
44          long start = System.currentTimeMillis();
45 46          //stream并行流                         包含10_0000_0000
47          Long sum = LongStream.rangeClosed(0L, 10_0000_0000L)
48                  .parallel()//并行计算
49                  .reduce(0,Long::sum);//调用Long下面的sum方法 输出结果
50 51          
52          long end = System.currentTimeMillis();
53          System.out.println("sum =" + sum + "时间:" + (end - start));
54      }
55  }
56 57

15、异步回调(Future)

Future 设计的初衷: 对将来的某个事件的结果进行建模

同步回调

我们常用的一些请求都是同步回调的,同步回调是阻塞的,单个的线程需要等待结果的返回才能继续执行。

异步回调

有的时候,我们不希望程序在某个执行方法上一直阻塞,需要先执行后续的方法,那就是这里的异步回调。我们在调用一个方法时,如果执行时间比较长,我们可以传入一个回调的方法,当方法执行完时,让被调用者执行给定的回调方法。

 1  package com.xing.future;
 2  3  import java.util.concurrent.CompletableFuture;
 4  import java.util.concurrent.ExecutionException;
 5  6  /**
 7   * 异步调用:CompletableFuture
 8   * 异步执行
 9   * 成功回调
10   * 失败回调
11   */
12  public class Demo01 {
13      public static void main(String[] args) throws ExecutionException, InterruptedException {
14       /*
15          //发起一个请求
16          //异步回调 没有返回值的异步回调
17          CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
18              try {
19                  TimeUnit.SECONDS.sleep(2);
20              } catch (InterruptedException e) {
21                  e.printStackTrace();
22              }
23              System.out.println(Thread.currentThread().getName() + "runAsync=>void");
24          });
25          System.out.println("11111");
26          completableFuture.get();//获取执行结果
27          */
28 29          //有返回值的异步回调
30          //Ajax 成功和失败的回调
31          //返回的是错误信息
32          CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
33              System.out.println(Thread.currentThread().getName() + "supplyAsync=>Integer");
34              //int i = 10/0;
35              return 1024;
36          });
37          System.out.println(completableFuture.whenComplete((t,u)->{//结果编译成功的时候返回  
38              //成功的时候t为1024 u为null
39              System.out.println("t=>" + t);//错的是时候t为null,
40              System.out.println("u=>" + u);//错的时候u打印错误信息 java.util.concurrent.CompletionException:java.lang.ArithmeticException: / by zero
41          }).exceptionally((e)->{//编译失败的时候返回
42              System.out.println(e.getMessage());//打印异常信息  java.lang.ArithmeticException: / by zero
43              return 2333;//可以获取错误的返回结果
44          }).get());
45      }
46 47  }
 
posted @ 2022-08-21 21:49  暴躁C语言  阅读(58)  评论(0编辑  收藏  举报