在我们传统的理解中,通讯应该是这个样子的,比如A和B之间通讯,A和B应该各自有个发件箱和一个收件箱,然后A通过A的发件箱将信息发送到B的收件箱内,同样B通过B的发件箱将信息发送到A的发件箱,如图:
但是在isolate中的通讯不是这样的,它的通讯模型比较特别.首先你要进程间通讯,你的每个进程必须要有个通讯用的收件箱,在isolate中这个收件箱类叫做ReceivePort,这个名字本身没什么问题,但是在理解模型时很不方便,所以你可以先把这个ReceivePort理解为一个收件箱,这个收件箱自带一个发件箱(ReceivePort中有个sendPort属性,为了方便理解,你可以把看到的port单词直接理解为box).所以我们要做的第一步就是创建这个收件箱
1
| var mainReciveBox = ReceivePort();
|
这个语句会自动创建一个这个语句所在线程的收件箱,比如你在main()函数里执行这个语句,那么这里创建的就是主线程的收件箱,假如现在我们在A线程里创建了这个收件箱,由于前面说过这个收件箱自带发件箱,所以A也有了一个发件箱
好了,现在我们创建一个线程B(具体创建方法等后面再说),同样我们在线程B里也创建一个属于线程B的收件箱,这样A和B两个线程都各自拥有了自己的收件箱和发件箱.
接下来就是比较特别的地方了,只要记住一个原则就比较容易理解了,就是自己的收件箱只能收到自己发件箱发来的消息,这个很重要,是理解这个通讯机制的关键.基于这个前提,那么假如B要给A发消息怎么办?因为A的收件箱只能收到自己A的发件箱发来的消息,所以解决的办法就是在创建线程B的时候创建一个A发件箱的副本传给B,这样就等于B拥有了一个A的发件箱,所以B就可以给A发消息了,同样,如果A要发消息给B,当B有了自己的发件箱后要第一个时间把自己的发件箱发一个给A,这样A和B之间就能相互通信了
主线程代码
1 2 3 4 5 6 7 8 9 10 11 12
| main() async { var mainReciveBox = ReceivePort(); print('主线程发件箱 的sendPort:${mainReciveBox.sendPort.hashCode}'); await Isolate.spawn<SendPort>(subThread, mainReciveBox.sendPort); }
|
子线程代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| subThread(SendPort mainSendBoxCopy) async { print('子isolate接收到 的sendPort:${mainSendBoxCopy.hashCode}'); var subReciveBox = new ReceivePort(); print('创建子isolate 的sendPort:${subReciveBox.sendPort.hashCode}'); mainSendBoxCopy.send(subReciveBox.sendPort); }
|
最后我们把完整的消息交互过程补上
主线程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| main() async { var mainReciveBox = ReceivePort(); print('主线程发件箱 的sendPort:${mainReciveBox.sendPort.hashCode}'); await Isolate.spawn<SendPort>(subThread, mainReciveBox.sendPort); SendPort subSendBox; mainReciveBox.listen((msg) { if (msg is SendPort) { subSendBox = msg; subSendBox.send("hoho1"); subSendBox.send("hoho2"); subSendBox.send("hoho3"); } else { print("主线程监听接收到的消息是:$msg"); } }); }
|
子线程完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| subThread(SendPort mainSendBoxCopy) async { print('子isolate接收到 的sendPort:${mainSendBoxCopy.hashCode}'); var subReciveBox = new ReceivePort(); print('创建子isolate 的sendPort:${subReciveBox.sendPort.hashCode}'); mainSendBoxCopy.send(subReciveBox.sendPort); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据1"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据2"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据3"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据4"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据5"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据6"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据7"); mainSendBoxCopy.send("来自子线程向父线程发送的消息 发送数据8"); await for (var msg in subReciveBox) { print("子isolate收到的消息:$msg"); } }
|
结果:
创建父isolate 的sendPort:232827375
子isolate接收到 的sendPort:232827375
创建子isolate 的sendPort:440139342
在主线程中收到了子线程的发件箱440139342
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据1
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据2
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据3
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据4
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据5
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据6
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据7
父ioslate 监听接收到的消息是:来自子线程向父线程发送的消息 发送数据8
子isolate收到的消息:hoho1
子isolate收到的消息:hoho2
子isolate收到的消息:hoho3
到这里就是先了现在之间的互相通讯了
大家有没觉得并不是那么称手,下回有空说一下稍微进阶一点的用法
原创文章,转载请注明出处,谢谢!(感谢同事柏的帮助)