Kotlin协程通信机制

IT技术2年前 (2022)更新 投稿用户
0

Java中的多线程通讯,总会涉及到共享状态(sharedmutablestate)的读写,有同步,死锁等问题要处理.

协程中的Channel用于协程间的通讯,它的宗旨是:
Donotcommunicatebysharingmemory;instead,sharememorybycommunicating.
Channelbasics
channels用于协程间的通讯,答应咱们在不同的协程间传递数据(astreamofvalues).
生产者-消费者形式
发送数据到channel的协程被称为producer,从channel接受数据的协程被称为consumer.
生产:send,produce.
消费:receive,consume.
当需求的时候,多个协程能够向同一个channel发送数据,一个channel的数据也能够被多个协程接纳.
当多个协程从同一个channel接纳数据的时候,每个元素仅被其间一个consumer消费一次.处理元素会自动将其从channel里删除.

Android


Channel的特点
Channel在概念上有点类似于BlockingQueue,元素从一端被加入,从另一端被消费.关键的差异在于,读写的办法不是blocking的,而是suspending的.
在为空或为满时.channel能够suspend它的send和receive操作.
Channel的封闭和迭代
Channel能够被封闭,说明没有更多的元素了.
取消producer协程也会封闭channel.
在receiver端有一种便利的方法来接纳:用for迭代.
看这个比如:
funmain()=runBlocking{valchannel=Channel()
launch{for(xin1..5)channel.send(x)
channel.close()//we’redonesending}//hereweprintreceivedvaluesusing`for`loop(untilthechannelisclosed)for(yinchannel)println(y)
println(“Done!”)
}
运行后会输出:
12345Done!
Processfinishedwithexitcode0
假如注释掉channel.close()就会变成:
1
2
3
4
5
Done没有被输出,程序也没有退出,这是由于接受者协程还在一直等候.
不同的Channel类型
库中定义了多个channel类型,它们的首要差异在于:
内部能够存储的元素数量;
send是否能够被挂起.
一切channel类型的receive办法都是相同的行为:假如channel不为空,接纳一个元素,不然挂起.
Channel的不同类型:
Rendezvouschannel:0尺度buffer,send和receive要meetontime,不然挂起.(默许类型).
Unlimitedchannel:无限元素,send不被挂起.
Bufferedchannel:指定巨细,满了之后send挂起.
Conflatedchannel:新元素会掩盖旧元素,receiver只会得到最新元素,send永不挂起.
创建channel:
valrendezvousChannel=Channel<String>()
valbufferedChannel=Channel<String>(10)
valconflatedChannel=Channel<String>(CONFLATED)
valunlimitedChannel=Channel<String>(UNLIMITED)
默许是Rendezvouschannel.
练习:剖析代码输出
看这段代码:
funmain()=runBlocking{
valchannel=Channel()
launch{
channel.send(“A1”)
channel.send(“A2”)log(“Adone”)
}
launch{
channel.send(“B1”)log(“Bdone”)
}
launch{
repeat(3){
valx=channel.receive()log(x)
}
}
}
funlog(message:Any?){
println(“[${Thread.currentThread().name}]$message”)
}
这段代码创建了一个channel,传递String类型的元素.
两个producder协程,分别向channel发送不同的字符串,发送结束后打印各自的”done”.
一个receiver协程,接纳channel中的3个元素并打印.
程序的运行输出成果会是怎样呢?
记住在Configurations中加上VMoptions:-Dkotlinx.coroutines.debug.能够看到协程信息.
答案揭晓:
[main@coroutine#4]A1[main@coroutine#4]B1[main@coroutine#2]Adone[main@coroutine#3]Bdone[main@coroutine#4]A2
答对了吗?
为什么会是这样呢?原因首要有两点:
这里创建的channel是默许的Rendezvous类型,没有buffer,send和receive必须要meet,不然挂起.
两个producer和receiver协程都运行在同一个线程上,readytoberesumed也仅仅加入了一个等候队列,resume要按顺序来.
这个比如在IntroductiontoCoroutinesandChannels中有一个视频说明.
别的,官方文档中还有一个ping-pang的比如,为了说明Channelsarefair.

© 版权声明
好牛新坐标 广告
版权声明:
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com

相关文章