我与 Kotlin 的爱恨情仇之浅谈 async/await - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liusd
V2EX    Kotlin

我与 Kotlin 的爱恨情仇之浅谈 async/await

  •  
  •   liusd 2017-05-26 15:04:25 +08:00 9547 次点击
    这是一个创建于 3060 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我与 Kotlin 的爱恨情仇之浅谈 async/await

    We all know that blocking is bad under a high load, that polling is a no-go, and the world is becoming more and more push-based and asynchronous. Man languages (starting with C# in 2012) support asynchronous programming through dedicated language constructs such as async/await keywords. In Kotlin, we generalized this concept so that libraries can define their own versions of such constructs, and async is not a keyword, but simply a function.

    写了前几篇文章之后,今天回来在想给大家聊点什么呢?整理文件的发现了一张照片,让我想起到了这个话题,至于是什么照片,不妨听我慢慢道来。

    async/await 是什么?

    我不知道你是否写过 c# ,不 严格意义上来说,是写过 2012 年之后的 c#,如果写过,那么 OK,我想这篇文章,你可以直接翻到最后啦,如果没有,那么我倒是冒昧的讲讲。

    Kotlin 1.1 版本更新中 ,介绍了 async/await 的基本用法。在文章开头我也引用了文中的描述。 Kotlin1.1 版本中引入了这个概念,可以自行实现,比如用 RX 来实现。

    从字面意思,async 异步, await 等待 ,就能看出来是为了解决异步任务的难题。

    我爱 async/await

    真的很爱,因为异步任务到处可见,一个提交表单,又或是加载一张图片,又或是普通的读写磁盘,都是非常耗时的。为了改善用户体验,往往我们会把这些耗时的 Task 放在后台 background 等事情处理好之后,回调给主线程更新视图。

    那么在没有 async/await 的时候,我们 Android 怎么活下来的呢?

    • asynctask 大概长这个样子:
     private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } 

    别哭,当年我们就是这么过来的。但遇到了太多的坑,这里就展开了的。

    • Java Runnable & Android Handler

      配合 ThreadPoolExecutor 确实可以解决大量问题,任务调度自己处理,再配合 Handler 来切换到主线程,完全可以满足日常需求。but 使用起来,还是很不爽,比较繁琐。

    • Java Future & Android Handler

      Runnable 大相径庭,这里就不在展开了的,具体可以看文档 [《 Future 》]( https://developer.android.com/reference/java/util/concurrent/Future.html

    那么有了 async/await 之后, 现在呢?

     fun main(args: Array<String>) { val future = async<String> { (1..5).map { await(startLongAsyncOperation(it)) // suspend while the long method is running }.joinToString("\n") } println(future.get()) } 

    async 是一个异步的 blok, 如果你不懂 blok,可以等会去看看我之前的一篇关于 block 的介绍 《我与 Kotlin 的爱恨情仇之浅谈 block 》。简单的说就是后面跟了一个 代码块,返回的是一个字符串类型。 block 里面做了一个简单的 一个 map 操作,每次循环都执行 await 等待的耗时操作。 如果在没有 async/await 出来之前,这里确实很难写到这么简洁。

    我不爱 async/await

    No, 到了这个节点,只是一个形式, 我非常喜欢这种简洁方式。非要让我说一个不爱的理由,那么我只能说:“ hi, 你为什么出来的这么晚???,以至于到现在我项目中还没有用到”。

    写在最后

    为什么会提到这个话题,只是因为整理照片的时候发现了以前痛苦的往事。 2014 年 有幸 去参加了 微软马拉松比赛c# 一个只是当年大学折腾过 ASP.NET 和被折磨到哭的ADO.NET, 尤其是后者往事不堪回首。如果您折磨过,请在楼下评论去按个 1。然而还是被公司强行带到微软 园区参加比赛,各种苦,因为完全没有接触过 WP

    还好 有幸 拿了第二名。

    但这次比赛,让我 真的有幸的接触了 2012 一年以后的.NET,完全是另外一个世界啦。写起来太爽了的。其中就包括 async/await (虽然内部实现还是 task), 所以当我看到 Kotlin 1.1 版本更新介绍的时候,WOW, 这不是当年的 .Net嘛, Kotlin 你终于也有了的哦。开心。

    《查看原文》

    23 条回复    2017-05-27 22:56:51 +08:00
    abbenyyy
        1
    abbenyyy  
       2017-05-26 15:33:22 +08:00
    那么对比 RxJava 如何?最近用 RxJava2 简直上瘾,事务流式处理太爽了。
    laxenade
        2
    laxenade  
       2017-05-26 15:33:28 +08:00 via Android
    终于有一个是 scala 里没有的了
    longaiwp
        3
    longaiwp  
       2017-05-26 16:46:42 +08:00
    看起来算是前辈了
    james
        4
    james  
       2017-05-26 17:15:59 +08:00
    @laxenade Scala 里面的 future 结合 for 本质是一样的呀,只是语法不一样。
    `for {a <- aFuture, b <- bFuture} yield a + b`
    ezreal
        5
    ezreal  
       2017-05-26 20:36:53 +08:00 via iPhone
    js 里都有
    iFlicker
        6
    iFlicker  
       2017-05-26 20:55:02 +08:00 via Android
    同想知道对比 RxJava,看起来简洁一些
    liusd
        7
    liusd  
    OP
       2017-05-26 21:57:25 +08:00
    @longaiwp 只是年纪比较大了而已。晚上下班回来跟大家一起唠唠嗑。
    liusd
        8
    liusd  
    OP
       2017-05-26 21:58:40 +08:00
    @ezreal 这个是个趋势。
    liusd
        9
    liusd  
    OP
       2017-05-26 21:59:20 +08:00
    @abbenyyy 啊哈 可以考虑一起用嘛。
    limhiaoing
        10
    limhiaoing  
       2017-05-26 22:04:16 +08:00
    当年也是因为 async/await 这个语法糖学的 C#。
    limhiaoing
        11
    limhiaoing  
       2017-05-26 22:14:22 +08:00
    @james
    你这个是 generator 吧? 感觉和 async 还是有些区别的。
    james
        12
    james  
       2017-05-26 22:36:13 +08:00
    @limhiaoing 本质是一样的。Generator 还更加灵活强大,async 和 await 可以认为是语法糖。你看 ES7 里面的 async/await 也是通过 es6 的 generator 来实现的。我写 JS 也都会用上 async/await,可写 scala 用它强大的 for 语法基本差不多。
    7sDream
        13
    7sDream  
       2017-05-27 01:20:47 +08:00
    我记得看过一个 PPT 说 Kotlin 的关注并发但决定并不拘泥与某一方式,编译器是通过把 suspend function 转换成状态机来实现的,能够支持各种不同方式……

    比如这里说的 ASync/AWait,Promise/Future 之类,还可以用 go/clojure 使用的 CSP 模型,也就是用 Channel 通信;还有 erlang/elixir 的无锁 actor 模型好像也行,当然 Java 的 Thread/Mutex 也可以……

    反正看上去很厉害的样子……

    1.1 里带的这个“官方”并发库里就有很多子库,提供了很多实现的例子,貌似 RxJava 的辅助工具也有一些: https://github.com/Kotlin/kotlinx.coroutines
    SoloCompany
        14
    SoloCompany  
       2017-05-27 02:26:50 +08:00
    如果你有关注,在去年发布 1.0 的时候,1.1 的蓝图就已经规划好了,其中 coroutine 就是重点中的重点

    至于语法糖,es7 那才叫语法糖,连 promise 都包不住完全暴露出来,对比一下 kotlin 的 suspendable function 和 es7 的 async function 不难发现它们有本质的区别,es7 里面的 await 是关键字,并且是强制的,如果你忘记写了,不管所在的 closure 环境是否 async function,得到的都将是个 promise,这使得同步代码转异步代码的难度以及调试的难度都加大了; kotlin 则不存在这个问题,因为压根就没有 await 关键字,所有 suspendable function 返回都是异步的
    kimown
        15
    kimown  
       2017-05-27 07:31:27 +08:00 via Android
    在 io 大会之前,v2 上就没看到 kotlin 的文章
    liusd
        16
    liusd  
    OP
       2017-05-27 11:31:11 +08:00
    @kimown 原因是 我以为大家都知道有这么新的 JVM 语言。。。结果 IO 大会之后才炸开锅了的。
    sagaxu
        17
    sagaxu  
       2017-05-27 13:21:22 +08:00
    @liusd 去年我就跑线上了,不过我是用在服务端,不是 android
    sagaxu
        18
    sagaxu  
       2017-05-27 13:22:29 +08:00
    @james 从能不能实现逻辑的角度看,scala 也可以看作是 Java 的语法糖
    sosloop
        19
    sosloop  
       2017-05-27 17:05:19 +08:00 via Android
    硬是把白话文写成了古文
    joesonw
        20
    joesonw  
       2017-05-27 17:27:37 +08:00
    @SoloCompany C#也是语法糖咯? 不 await 返回的是 Task<>. 你没搞清楚 async/await 是为了什么. 我可以先执行一个异步方法, 但我此时不需要结果, 可以先执行其他的代码, 最后需要的时候再 await, 如果此时任务已经跑完了就直接返回结果.
    liusd
        21
    liusd  
    OP
       2017-05-27 20:48:19 +08:00
    @chenpipguge 哈哈哈哈哈
    liusd
        22
    liusd  
    OP
       2017-05-27 20:49:26 +08:00
    CodingPuppy
        23
    CodingPuppy  
       2017-05-27 22:56:51 +08:00
    @kimown #15 说实话,你 out 了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1595 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 16:24 PVG 00:24 LAX 09:24 JFK 12:24
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86