CompletableFuture中的thenRun和thenRunAsync方法

需求:

我需要在做完第一件事情后,再做第二件事情。

代码编程:

    @Resource(name = "globalThreadPool")
    private ThreadPoolExecutor threadPoolExecutor;
    
	CompletableFuture.runAsync(() -> {
	做第一件事情;
	},threadPoolExecutor).thenRun(()->{
   做第二件事情
   });

其中做第二件事情的时候CompletableFuture提供了三个方法,源码如下。
CompletableFuture源码:

public CompletableFuture<Void> thenRun(Runnable action) {
    return uniRunStage(null, action);
}


public CompletableFuture<Void> thenRunAsync(Runnable action) {
    return uniRunStage(asyncPool, action);
}


public CompletableFuture<Void> thenRunAsync(Runnable action,
                                            Executor executor) {
    return uniRunStage(screenExecutor(executor), action);
}

可以看到它们都内部调用了uniRunStage(Executor e, Runnable f) 方法:

    private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
        if (f == null) throw new NullPointerException();
        CompletableFuture<Void> d = new CompletableFuture<Void>();
        if (e != null || !d.uniRun(this, f, null)) {
            UniRun<T> c = new UniRun<T>(e, d, this, f);
            push(c);
            c.tryFire(SYNC);
        }
        return d;
    }

分析

thenRun方法

可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的null,所以它是使用的是执行上一个任务的线程池。

  • 也就是说,如果你执行第一个任务的时候,传入了一个线程池,当执行第二个任务的时候调用的是thenRun方法,则第二个任务和第一个任务是公用同一个线程池。
thenRunAsync(Runnable action)方法

可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的asyncPool,所以它是使用的默认的ForkJoin线程池。
private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

  • 也就是说,如果你执行第一个任务的时候,传入了一个线程池,当执行第二个任务的时候调用的是thenRunAsync(Runnable action)方法,则第一个任务使用的是你传入的线程池,第二个任务使用的是ForkJoin线程池,由于ForkJoin线程池是整个应用程序公用的,比如stream使用方法parallel()进行并行运算的时候也是用的ForkJoin线程池,该线程池可以在程序启动的时候进行设置,详情请百度。由于是ForkJoin线程池是公用的,所以,不建议你在不知道程序其他地方哪里还会使用该线程池的情况下使用。
thenRunAsync(Runnable action,Executor executor)方法

可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的是外部传入的自定义线程池,所以它是使用的你指定的线程池。

  • 也就是说,如果你执行第一个任务的时候,传入了A线程池,当执行第二个任务的时候调用的是thenRunAsync(Runnable action,Executor executor)方法并传入了B线程池,则第一个任务使用的是A线程池,第二个任务使用的是B线程池。

版权声明:本文为liushuyul原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>