Kotlin轻量级线程:协程<一>

1、背景

    在硬件发展过程中,最初使用单核单CPU到后期的单核多CPU,再到多核多CPU,貌似已经到了极限,但是单核CPU的性能还在不停的提升,如果说多进程对应多CPU、多线程对应多核CPU,协程的目的就是在充分利用不断提高性能的单核CPU潜能。在业务开发过程中有很多性能瓶颈的耗时操作,比如网络IO、文件IO等。在使用Java做Android开发的时候,为了将耗时操作放在子线程去完成,大部分解决手段是通过异步回调的方式来实现,回调代码写起来比较繁琐以及可读性也不是很友好。

      协程使用协程挂起来提供一种避免阻塞线程,并用更简单可控的操作替代线程阻塞的方法,使异步回调的方法看上去是同步的方式,这样,我看可以按照串行的思维模式去组织原本分散在不同上下文环境中的代码逻辑,避免了处理复杂状态同步的问题,增加写代码的直观性和阅读友好性。

2、协程的概念

       协程是创造出来解决异步问题,线程的调度是操作系统层面完成是抢占式的;协程是非抢占式的,是协作运行的,是由应用层完成调度,协程在挂起的时候不会堵塞线程,只会将当前运行的状态存在内存中,当协程执行完成后,会恢复之前保存的状态继续运行。

3、使用

下面将使用协程实现一个主线程发启按钮点击,启动一个协程去做一个耗时任务,完成耗时任务后,将结果返回到UI线程的异步耗时操作流程。

启动协程

在接收到点击事件的时候我们只是调用了ContextAsyncCoroutineManager的startCoroutine方法,然后将耗时操作函数传以及后续处理的代码block传入;ContextAsyncCoroutineManager封装了启动协程的代码,代码如下:

ContextAsyncCoroutineManager

可以看到ContextAsyncCoroutineManager协程入口启动函数startCoroutine需要传入一个被suspend关键之修饰的block代码块,协程启动处需要使用suspend关键字修饰,在按钮被点击的时候,我们传入的函数是calculateAndJointText,做一个字符串拼接,然后每次休眠200毫的耗时任务;这里有一个AsyncTask类器代码:

AsyncTask

AsyncTask是处理耗时操作的线程池,在处理耗时操作的时候启动一个线程,将耗时任务放在该线程池中去处理。在平时开发过程中都会有自己的线程池管理应用的线程,这里只是一个很简易的线程池做一个演示。

调用block.startCoroutine(ContextContinuation(AsyncContext()))函数启动协程的时候需要传入了一个ContextContinuation,ContextContinuation的实例化又传入一个AsyncContext,其中ContextContinuation的具体实现如下:

ContextContinuation

Continuation:协程的编译记住状态特征主要实现者就是这个类,是描述程序控制状态的抽象,通过数据结果来表示执行到指定位置的计算过程,其结构可以由程序程序语言访问;即当一个协程执行到什么地方,需要用到什么field或者保存什么状态,这些过程都在当前运行时的这个实例中管理;

ContextContinuation是继承自Continuation,当协程执行完成,在耗时代码块内调用continuation.resume(textResult)的时候会回调到ContextContinuation的resumeWith里;

AsyncContext

AsyncContext:这里的作用是使用Context将工作线程切换到UI线程,替换Continuation到主专门做住线程切换的一个UIContinuationWrapper类,每个ContextContinuation可以有多个CoroutineContext;

协程Context,每个协程运行的时候都会有一个或者多个CoroutineContext对象,每个Context都有属于自己的一个Key来标记自己。我们的AsyncContext的Key是ContinuationInterceptor类型,并且实现了ContinuationInterceptor接口,上面的interceptContinuation函数可以拦截外部启动协程传入的Continuation对象,我们的需求是使用该特性做一次Continuation的篡改行为,替换为定义专门做UI线程切换的UIContinuationWrapper,在自己篡改好后,不能直接拦截掉本次Continuations实例,需要继续传递给其它的拦截者。在结果回来调用就会调用到UIContinuationWrapper的resumeWith方法,从而完成将执行结果返回到UI线程,实现自动切换线程。

UiContinuationWrapper

使用Kotlin协程基础API实现一次异步任务的代码就已经完成,本次只是借助这个小例子来介绍相关的一些概念。其实还有很多具体使用和实现没有讲,比如:在开发过程中其实我们肯定会涉及到多线程传值的问题,也可以通过我们的Context去完成;以及我们需要使用协程基础API去封装一个比较通用完善的Kotlin异步任务框架等。

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

推荐阅读更多精彩内容