CompletableFuture线程池执行多个任务进行链式、组合等助理使用

2023-11-10

2.1 CompletableFuture简介


使用线程池执行任务没法直接对多个任务进行链式组合等处理,或者说实现起来比较麻烦需要借助并发工具类才能完成。

CompletableFuture实现了对任务编排的能力。借助这项能力,可以轻松地组织不同任务的运行顺序、规则以及方式。从某种程度上说,这

项能力是它的核心能力。

2.2 异步来执行一个任务


无返回值的方法:

// 无返回值方法
runAsync(runnable):  CompletableFuture<Void>以异步方式启动一个任务并在默认的线程池(ForkJoinPool)执行
runAsync(runnable,executor):CompletableFuture<Void>    以异步方式启动一个任务并在指定的线程池(executor)执行
代码演示:
publicstaticvoidmain(String[] args) throwsIOException, ExecutionException, InterruptedException {
    runAsyncTest01() ;
    System.out.println("业务线程执行完毕了...");
    System.in.read() ;      // 让JVM不要立即退出
}
​
publicstaticvoidrunAsyncTest01() {
  CompletableFuture.runAsync(() ->System.out.println(Thread.currentThread() +"执行了一个任务")) ;
}
​
publicstaticvoidrunAsyncTest02() {
  CompletableFuture.runAsync(() ->System.out.println(Thread.currentThread() +"执行了一个任务") , service) ;
}

有返回值方法:

// 有返回值方法
supplyAsync(supplier): CompletableFuture<U>   以异步方式启动一个任务并在默认的线程池(ForkJoinPool)执行。
supplyAsync(supplier,executor):CompletableFuture<U>  以异步方式启动一个任务并在指定的线程池(executor)执行。
代码演示:
publicstaticvoidsupplyAsyncTest02() throwsExecutionException, InterruptedException {
    CompletableFuture<Integer>supplyAsync=CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10;
    },service);
    Integercount=supplyAsync.get();
    System.out.println(count);
}
​
publicstaticvoidsupplyAsyncTest01() throwsExecutionException, InterruptedException {
    CompletableFuture<Integer>supplyAsync=CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10;
    });
    Integercount=supplyAsync.get();  // 获取异步线程执行结果
    System.out.println(count);
}

2.3 whenComplete方法


可以在任务执行完毕以后(不论是正常执行完毕还是出现异常)执行某一个操作。

  • 正常完成:whenComplete返回结果和上级任务一致,异常为null;

  • 出现异常:whenComplete返回结果为null,异常为上级任务的异常;

相关方法:

whenComplete(action) 使用当前线程执行一个动作,不开启额外的线程

whenCompleteAsync(action) 在默认的线程池中开启一个线程执行该动作

whenCompleteAsync(action, executor) 在指定的线程池中开启一个线程执行该动作

注意:如果上一次任务执行完毕以后产生了异常,那么此时在调用get方法获取结果的时候就会抛出异常。

publicstaticvoidwhenCompleteTest01() throwsExecutionException, InterruptedException {
    /**
         * result参数表示的是上一次任务执行完成以后的结果
         * e:表示的是异常对象
         */
    CompletableFuture<Integer>supplyAsync=CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10;
    },service).whenComplete((result , e) -> {  // 使用main线程执行当前任务
        if(e==null) {
            System.out.println(Thread.currentThread() +"上一次任务正常执行完成了,任务的返回结果为:"+result);
        }else {
            System.out.println(Thread.currentThread() +"上一次任务执行时产生了异常,任务的返回结果为:"+result);
        }
    });
​
    Integerinteger=supplyAsync.get(); // 获取异步任务的结果,如果whenComplete上一次执行的产生异常了,那么在调用该方法的时候就会报错
    System.out.println(integer);
}
​
publicstaticvoidwhenCompleteTest02() throwsExecutionException, InterruptedException {
    /**
         * result参数表示的是上一次任务执行完成以后的结果
         * e:表示的是异常对象
         */
    CompletableFuture<Integer>supplyAsync=CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10/0 ;
    },service).whenComplete((result , e) -> {
        if(e==null) {
            System.out.println(Thread.currentThread() +"上一次任务正常执行完成了,任务的返回结果为:"+result);
        }else {
            System.out.println(Thread.currentThread() +"上一次任务执行时产生了异常,任务的返回结果为:"+result);
        }
    }).exceptionally((e) -> {   // 配合exceptionally方法可以在产生异常以后返回一个默认值。
        System.out.println(e);
        return20 ;
    });
​
    Integerinteger=supplyAsync.get();
    System.out.println(integer);
}

2.4 thenRun方法


相关方法:

// 无法获取到上一次任务的执行结果

thenRun(runnable): 接下来跑一个任务,以当前线程作为跑任务的线程,不开额外的异步线程

thenRunAsync(runnable): 接下来跑一个任务,用默认线程池新开一个异步线程

thenRunAsync(runnable,executor): 接下来跑一个任务,用指定线程池新开一个异步线程

上述方法和whenComplete比较区别:thenXXX无法获取到上一个任务产生的异常。当上一个任务执行完毕以后产生了异常,那么该任务无法执行。

代码演示:

publicstaticvoidthenRunAsyncTest01() {
    CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10  ;
    },service).thenRun(() -> {
        System.out.println(Thread.currentThread() +"---上一个任务执行完毕了,执行该任务");
    });
}

2.5 thenAccept方法


相关方法:

thenAccept(consumer): 接下来跑一个任务,接受到上次的结果,以当前线程作为跑任务的线程,不开额外的异步线程

thenAcceptAsync(consumer): 接下来跑一个任务,接受到上次的结果,用默认线程池新开一个异步线程

thenAcceptAsync(consumer,executor) 接下来跑一个任务,接受到上次的结果,用指定线程池新开一个异步线程

代码演示:

publicstaticvoidthenAcceptTest01() {
    CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10 ;
    },service).thenAccept((result) ->System.out.println(result*10));
}

2.6 thenApply方法


相关方法:

thenApply(function) 接下来跑一个任务,接受到上次的结果,并且返回一个新的结果,以当前线程作为跑任务的线程,不开额外的异步线程

thenApplyAsync(function) 接下来跑一个任务,接受到上次的结果,并且返回一个新的结果,用默认线程池新开一个异步线程

thenApplyAsync(function, executor)接下来跑一个任务,接受到上次的结果,并且返回一个新的结果,用指定线程池新开一个异步线程

代码演示:

publicstaticvoidthenApplyAsyncTest01() throwsExecutionException, InterruptedException {
    Integercount=CompletableFuture.supplyAsync(() -> {
        System.out.println(Thread.currentThread());
        return10;
    }, service).thenApplyAsync((result) -> {
        System.out.println(Thread.currentThread() +"---"+result*10);
        returnresult*2;
    }).get();  // 获取最终的执行结果
    System.out.println(count);
}

2.7 编排任务


需求:在控制台按照顺序输出"haha"、"hehe"、"heihei"

publicstaticvoidcompletableTash() throwsExecutionException, InterruptedException {
    CompletableFuture.runAsync(() ->System.out.println("haha")).thenRun(() ->System.out.println("hehe"))
        .thenRun(() ->System.out.println("heihei")) ;

}

2.8 组合多任务


相关方法:

CompletableFuture<Void>allOf(CompletableFuture<?>... cfs) 当所有的任务执行完毕以后,线程再向下进行执行

CompletableFuture<Object>anyOf(CompletableFuture<?>... cfs) 当任意一个任务执行完毕以后,线程再向下进行执行

CompletableFuture<Void>runAfterBoth(other,action) 当两个任务执行完毕以后在执行一个新的任务

代码演示:

privatestaticvoidallOf() throwsExecutionException, InterruptedException {
​
    CompletableFuture<Void>completableFuture1=CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(3000);
        } catch (InterruptedExceptione) {
            e.printStackTrace();
        }
        System.out.println("任务1执行完毕");
    });
​
​
    CompletableFuture<Void>completableFuture2=CompletableFuture.runAsync(() -> {
        try {
            Thread.sleep(10000);
        } catch (InterruptedExceptione) {
            e.printStackTrace();
        }
        System.out.println("任务2执行完毕");
    });
​
    // CompletableFuture.anyOf(completableFuture1 , completableFuture2).join() ;  // 调用get方法或者join方法阻塞当前线程
    // CompletableFuture.allOf(completableFuture1 , completableFuture2).join() ;
    completableFuture1.runAfterBoth(completableFuture2 , () ->System.out.println("任务三执行")) ;
    System.out.println("heheihei");
​
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CompletableFuture线程池执行多个任务进行链式、组合等助理使用 的相关文章

随机推荐