CompletableFuture

CompletableFuture


简介

扩展 Future 功能,通过 CompletionStage 提供函数式编程的能力,简化异步编程

基本用法

  • CompletableFuture ,实现了 Future<T>, CompletionStage<T> 两个接口。
  • Executor 参数可以手动指定线程池,否则默认 ForkJoinPool.commonPool() 系统级公共线程池。这些线程都是守护线程,主线程结束守护线程不结束,只有JVM关闭时,生命周期终止。
  • 以 Async 结尾的方法都是异步执行,即到线程池取个新线程执行

创建

  • supplyAsync
    创建有返回值的任务 参数 Supplier
  • runAsync
    建没有返回值的任务 参数 Runnable
  • completedFuture
    创建已完成的任务 参数为值

消费

  • whenComplete whenCompleteAsync
    消费任务结果 参数 BiConsumer
  • exceptionally
    消费任务异常 参数 Function
  • handle handleAsync
    消费任务结果和异常 参数 BiFunction

变换

  • thenApply thenApplyAsync
    有入参有返回值 参数 Function

  • thenAccept thenAcceptAsync
    有入参无返回值 参数 Consumer

  • thenRun thenRunAsync
    无入参无返回值 参数 Runnable

  • thenCompose thenComposeAsync
    构成新任务 参数 Function

组合

  • thenCombine thenCombineAsync
    双线有入参有返回值 参数 CompletionStage BiFunction

  • thenAcceptBoth thenAcceptBothAsync
    双线有入参无返回值 参数 CompletionStage BiConsumer

  • runAfterBoth runAfterBothAsync
    双线无入参无返回值 参数 CompletionStage Runnable

  • applyToEither applyToEitherAsync
    二选快有入参有返回值 参数 CompletionStage Function

  • acceptEither acceptEitherAsync
    二选快有入参无返回值 参数 CompletionStage Consumer

  • runAfterEither runAfterEitherAsync
    二选快无入参无返回值 参数 CompletionStage Runnable

群体

  • anyOf
    只要有完成即触发有返回值 参数 CompletableFuture...
  • allOf
    全部完成才触发无返回值,可接收异常 参数 CompletableFuture...
fun testAnyOfAndAllOf() {
    val f1: CompletableFuture<String> = CompletableFuture.supplyAsync {
        TimeUnit.SECONDS.sleep(2)
        return@supplyAsync Thread.currentThread().name
    }.whenComplete { t, u ->
        println("t1: ${System.currentTimeMillis()}: ${Thread.currentThread().name}: $t $u")
    }

    val f2: CompletableFuture<String> = CompletableFuture.supplyAsync {
        TimeUnit.SECONDS.sleep(1)
        return@supplyAsync Thread.currentThread().name
    }.whenCompleteAsync { t, u ->
        println("t2: ${System.currentTimeMillis()}: ${Thread.currentThread().name}: $t $u")
    }

    CompletableFuture.anyOf(f1, f2)
        .whenComplete { t, u ->
            println("anyOf: ${System.currentTimeMillis()}: ${Thread.currentThread().name}: $t $u")
        }

    CompletableFuture.allOf(f1, f2)
        .whenComplete { t, u ->
            println("allOf: ${System.currentTimeMillis()}: ${Thread.currentThread().name}: $t $u")
        }.join()
}
t2: 1550851312825: ForkJoinPool.commonPool-worker-2: ForkJoinPool.commonPool-worker-2 null
anyOf: 1550851312825: ForkJoinPool.commonPool-worker-2: ForkJoinPool.commonPool-worker-2 null
t1: 1550851313822: ForkJoinPool.commonPool-worker-1: ForkJoinPool.commonPool-worker-1 null
allOf: 1550851313822: ForkJoinPool.commonPool-worker-1: null null

完成

  • complete completeExceptionally cancel
    触发完成
  • isDone isCompletedExceptionally isCancelled
    判断任务是否已经结束

获取结果

  • get
    阻塞等待,获取任务结果,会抛出 ExecutionException InterruptedException CancellationException
  • join
    阻塞等待,获取任务结果,异常 CompletionException CancellationException
  • getNow
    立即取到结果,任务未结束则返回传入参数,异常 CompletionException CancellationException

切换线程

使用 Executor 切换执行任务线程,例如在 Android 中在主线程和子线程切换

fun testExecutor() {
    CompletableFuture.supplyAsync(Supplier {
        TimeUnit.SECONDS.sleep(2)
        println("t1: ${Thread.currentThread().name}") // t1: pool-1-thread-1
        return@Supplier "t1"
    }, AppExecutors.io).thenApplyAsync(Function<String, String> {
        println("t2: ${Thread.currentThread().name}") // t2: main
        return@Function "$it.t2"
    }, AppExecutors.main).thenApplyAsync(Function<String, String> {
        println("t3: ${Thread.currentThread().name}") // t3: pool-2-thread-1
        return@Function "$it.t3"
    }, AppExecutors.single).whenCompleteAsync(BiConsumer { t, u ->
        println("t4: ${Thread.currentThread().name}: $t $u") // t4: main: t1.t2.t3 null
    }, AppExecutors.main)
}

object AppExecutors {
    val io: ExecutorService by lazy {
        Executors.newCachedThreadPool()
    }

    val compute: ExecutorService by lazy {
        val threadCount = 3
        Executors.newFixedThreadPool(threadCount)
    }

    val single: ExecutorService by lazy {
        Executors.newSingleThreadExecutor()
    }

    val main: Executor by lazy {
        MainThreadExecutor()
    }

    private class MainThreadExecutor : Executor {
        private val mainThreadHandler: Handler = Handler(Looper.getMainLooper())

        override fun execute(command: Runnable?) {
            mainThreadHandler.post(command);
        }
    }
}

参考

CompletableFuture
Java8新特性整理之CompletableFuture:组合式、异步编程(七)
CompletableFuture 使用详解
个人愚见:分布式框架中使用CompletableFuture提高效率
Java并发编程系列一:Future和CompletableFuture解析与使用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容