FLUTTER 中 Isolate 的一个例子.
isolate
起因
最近看了一点isolate的东西, 自己写了一个例子.
普通的的 consummer-producer例子是只有前后两端的,实际上,会把前后两端再进行包装.
我这里这个例子,是把这个层级扩充,变成4层.
A((消费者))--定单--> B((小商店))--定单-->C((批发商))--定单-->D((加工厂))
D--运送-->C--运送-->B--运送-->A
消费者 consummer 是一个Future,发送请求,等待回复, 不关心中间过程.
小商店 seller 是主线程的处理函数,响应consummer的请求,并把请求发送给次线程的处理函数,
批发商 wholesale 是次线程的任务分发函数,可以把任务按同步的方式分发,也可以按异步的方式分发,我的例子是异步方式.
加工厂 producer 是执行任务的api, future. 在次线程执行.
同时,也要定义好前后通讯的信息的格式.
代码
dart代码,flutter中的代码就不放了.
import 'dart:isolate';
typedef FutureApiRets = Future<ApiRets> Function(ApiArgs args);
//api的参数的形式
class ApiArgs {
List<dynamic> list;
Map<dynamic, dynamic> map;
ApiArgs(this.list, this.map);
@override
String toString() {
return {
'ApiArgs': {'list': this.list, 'map': this.map}
}.toString();
}
}
//api的返回值的形式
class ApiRets {
List<dynamic> list;
Map<dynamic, dynamic> map;
ApiRets(this.list, this.map);
@override
String toString() {
return {
'ApiRets': {'list': this.list, 'map': this.map}
}.toString();
}
}
//seller 到 wholesale 的消息的格式
class Msg<T> {
T msg;
SendPort sendPort;
String apiName;
ApiArgs apiArgs;
Msg(this.msg, ReceivePort receivePort, {this.apiName = "", this.apiArgs}) : sendPort = receivePort.sendPort;
}
//封装 seller,wholesale 到一个类里,同时把线程的初始化和结束功能写出来.
class IsolateTest {
static SendPort sendPort;
static Isolate isolate;
static bool inited = false;
//seller类.
static Future<K> seller<T, K>(T msg, {String apiName, ApiArgs args}) async {
print("seller start++:msg->${msg.toString()}");
var rec = ReceivePort();
//与wholescale通过sendPort通讯
IsolateTest.sendPort.send(Msg<T>(msg, rec, apiName: apiName, apiArgs: args));
print("seller wait===:msg->${msg.toString()}");
K ret = (await rec.first) as K;
print("seller end----:msg->${msg.toString()}");
return ret;
}
//wholesale功能,执行在次线程里
static Future wholesale(Msg message) async {
print('wholesale start');
ApiTest().name = 'worker';
ReceivePort port = ReceivePort();
message.sendPort.send(port.sendPort);
print('wholesale waiting');
int count = 0;
//不断的接受数据
await for (Msg msg in port) {
SendPort reply = msg.sendPort;
if (reply == null) continue;
print("wholesale start++:msg->${msg.msg}:count->$count");
count++;
var ret;
//根据api的名称来调用
if (msg.apiName != "") {
var s = () async {
var ret;
try {
FutureApiRets api = ApiTest().apiMap[msg.apiName];
if (api != null) {
ret = await api(msg.apiArgs);
}
} catch (e) {
print(e.toString());
}
return ret;
};
s().then((value) {
print("wholesale end----:msg->${msg.msg}:count->$count");
reply.send(value);
});
} else {
print("wholesale end----:msg->${msg.msg}:count->$count");
reply.send(ret);
}
}
print('wholesale over');
}
//创建次线程
static Future createIsolate() async {
if (!inited) {
print('create isolate start');
ReceivePort rec = ReceivePort();
Msg msg = Msg('000', rec);
isolate = await Isolate.spawn(wholesale, msg);
sendPort = await rec.first;
inited = true;
print('create isolate finish');
}
}
//结束次线程
static closeIsolate() {
print('close isolate');
if (isolate != null) {
isolate.kill(priority: Isolate.immediate);
isolate = null;
inited = false;
}
}
}
//次线程内,执行具体任务的api,封装在一个类里,
class ApiTest {
static ApiTest _ins;
factory ApiTest() => _ins ?? ApiTest._fac();
ApiTest._fac() {
this.name = '';
//把api按名字做索引,是否可以重载[]或nosuchmethod来改进?
this.apiMap = {
'apiA': this.apiA,
'apiB': this.apiB,
'apiC': this.apiC,
};
}
String name;
Map<String, FutureApiRets> apiMap;
//apis
Future<ApiRets> apiA(ApiArgs args) async {
print("producer apiA+++:name:[${this.name}],args:${args.toString()}");
await Future.delayed(Duration(seconds: 3));
ApiRets ret = ApiRets(["apiA"], {});
print("producer apiA---:name:[${this.name}],args:${ret.toString()}");
return ret;
}
Future<ApiRets> apiB(ApiArgs args) async {
print("producer apiB+++:name:[${this.name}],args:${args.toString()}");
await Future.delayed(Duration(seconds: 4));
ApiRets ret = ApiRets(["apiB"], {});
print("producer apiB---:name:[${this.name}],args:${ret.toString()}");
return ret;
}
Future<ApiRets> apiC(ApiArgs args) async {
print("producer apiC+++:name:[${this.name}],args:${args.toString()}");
await Future.delayed(Duration(seconds: 5));
ApiRets ret = ApiRets(["apiC"], {});
print("producer apiC---:name:[${this.name}],args:${ret.toString()}");
return ret;
}
}
//用户的调用测试
Future consumer(int count, String name, String apiName) async {
ApiArgs args = ApiArgs([name, count], {});
print('consumer start++:$name,$count,${args.toString()}');
ApiRets ret = await IsolateTest.seller<String, ApiRets>(name, apiName: apiName, args: args);
print('consumer end----:$name,$count,${ret.toString()}');
}
main(List<String> args) async {
await IsolateTest.createIsolate();
await Future.wait<dynamic>([
consumer(1, 'aaa', 'apiA'),
consumer(2, 'aaa', 'apiB'),
consumer(3, 'aaa', 'apiC'),
consumer(4, 'bbb', 'apiA').then((value) => consumer(5, "ccc", 'apic')),
]).whenComplete(() async {
await IsolateTest.closeIsolate();
});
}
运行结果
create isolate start
wholesale start
wholesale waiting
create isolate finish
consumer start++:aaa,1,{ApiArgs: {list: [aaa, 1], map: {}}}
seller start++:msg->aaa
seller wait===:msg->aaa
consumer start++:aaa,2,{ApiArgs: {list: [aaa, 2], map: {}}}
seller start++:msg->aaa
seller wait===:msg->aaa
consumer start++:aaa,3,{ApiArgs: {list: [aaa, 3], map: {}}}
seller start++:msg->aaa
seller wait===:msg->aaa
consumer start++:bbb,4,{ApiArgs: {list: [bbb, 4], map: {}}}
seller start++:msg->bbb
seller wait===:msg->bbb
wholesale start++:msg->aaa:count->0
producer apiA+++:name:[],args:{ApiArgs: {list: [aaa, 1], map: {}}}
wholesale start++:msg->aaa:count->1
producer apiB+++:name:[],args:{ApiArgs: {list: [aaa, 2], map: {}}}
wholesale start++:msg->aaa:count->2
producer apiC+++:name:[],args:{ApiArgs: {list: [aaa, 3], map: {}}}
wholesale start++:msg->bbb:count->3
producer apiA+++:name:[],args:{ApiArgs: {list: [bbb, 4], map: {}}}
producer apiA---:name:[],args:{ApiRets: {list: [apiA], map: {}}}
wholesale end----:msg->aaa:count->4
seller end----:msg->aaa
consumer end----:aaa,1,{ApiRets: {list: [apiA], map: {}}}
producer apiA---:name:[],args:{ApiRets: {list: [apiA], map: {}}}
wholesale end----:msg->bbb:count->4
seller end----:msg->bbb
consumer end----:bbb,4,{ApiRets: {list: [apiA], map: {}}}
consumer start++:ccc,5,{ApiArgs: {list: [ccc, 5], map: {}}}
seller start++:msg->ccc
seller wait===:msg->cccwholesale start++:msg->ccc:count->4
wholesale end----:msg->ccc:count->5
seller end----:msg->ccc
consumer end----:ccc,5,null
producer apiB---:name:[],args:{ApiRets: {list: [apiB], map: {}}}
wholesale end----:msg->aaa:count->5
seller end----:msg->aaa
consumer end----:aaa,2,{ApiRets: {list: [apiB], map: {}}}
producer apiC---:name:[],args:{ApiRets: {list: [apiC], map: {}}}
wholesale end----:msg->aaa:count->5
seller end----:msg->aaa
consumer end----:aaa,3,{ApiRets: {list: [apiC], map: {}}}
close isolate
注意到中间 有部分的显示有问题.
seller start++:msg->ccc
seller wait===:msg->cccwholesale start++:msg->ccc:count->4
wholesale end----:msg->ccc:count->5
这里, 我分析是主次线程同时调用print()的时候,产生的乱码.
FLUTTER 中 Isolate 的一个例子.的更多相关文章
- mysql中case的一个例子
最近遇到一个问题: year amount num 1991 1 1.1 1991 2 1.2 1991 3 1.3 1992 1 2.1 1992 2 2.2 1992 3 3.3 把上面表格的数据 ...
- flutter中的路由跳转
在前面的基本路由和命名路由中,都演示了如何进行路由跳转,并且在路由跳转以后,可以借用系统自带的按钮就行返回上一级,当然了,也可以自定义按钮返回上一级. 返回上一级 在前面的例子中,当从Home.dar ...
- 从一个例子中体会React的基本面
[起初的准备工作] npm init npm install --save react react-dom npm install --save-dev html-webpack-plugin web ...
- Spark小课堂Week7 从Spark中一个例子看面向对象设计
Spark小课堂Week7 从Spark中一个例子看面向对象设计 今天我们讨论了个问题,来设计一个Spark中的常用功能. 功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load() ...
- SWT中ole/activex实践--操作word的一个例子
http://setting.iteye.com/blog/747295 ———————————————————————————————————————————————— 这几年,做了很多word/e ...
- Java编程思想中关于闭包的一个例子
Java编程思想中的一个例子,不是很理解使用闭包的必要性,如果不使用闭包,是不是有些任务就不能完成?继续探索. package InnerClass; interface Incrementable ...
- Android中Service的一个Demo例子
Android中Service的一个Demo例子 Service组件是Android系统重要的一部分,网上看了代码,很简单,但要想熟练使用还是需要Coding. 本文,主要贴代码,不对Servic ...
- session中删除数组中的某一个值 - 购物车例子 - jsp
这篇随笔简单的讲一下在session中移除数组中的某一项内容,比如这里有一个购物车其中有两件商品,需要移除其中洗发水这一件商品. 其实在这个session对象中存储了一个数组,在订购页面时选择商品加入 ...
- 理解 Flutter 中的 Key
概览 在 Flutter 中,大概大家都知道如何更新界面视图: 通过修改 Stata 去触发 Widget 重建,触发和更新的操作是 Flutter 框架做的. 但是有时即使修改了 State,Flu ...
- Flutter中管理路由栈的方法和应用
原文地址:https://www.jianshu.com/p/5df089d360e4 本文首先讲的Flutter中的路由,然后主要讲下Flutter中栈管理的几种方法. 了解下Route和Navig ...
随机推荐
- Splashtop用于远程实验室的功能得到增强
加利福尼亚州圣何塞,2020年8月11日,远程访问和远程支持解决方案的领导者Splashtop Inc. 宣布更新其 Splashtop for Remote Labs 产品.该产品旨在帮助学生通 ...
- 从 p12 格式 SSL 证书解出 pem 格式公钥私钥给 Postman 使用
目的 Postman 的(非 Chrome 扩展版的)app 并不能读取系统中的客户端证书,这种调试要发送客户端证书的 https 请求的时候就得自己另外设置.系统直接导出证书有 cer 和 p12 ...
- 配置Ingress支持HTTPS访问(二):使用cert-manager申请证书
目录 一.系统环境 二.前言 三.Let's Encrypt和cert-manager简介 四.部署cert-manager 4.1 安装cert-manager 4.2 创建clusterissue ...
- navicat premium 15 下载和激活
Navicat Premium 15 下载地址 链接:https://pan.baidu.com/s/1bL-M3-hkEa4M-547giVjYQ?pwd=1107 推荐安装参考地址:https:/ ...
- Android 13 - Media框架(4)- MediaPlayerService
关注公众号免费阅读全文,进入音视频开发技术分享群! MediaPlayerService是android的多媒体框架的核心服务之一,该服务存储有android平台所支援的编解码器信息,管理所有通过Me ...
- Java方法传参中"..."的作用
# Java方法传参中 `...` 类型名 介绍 - <font color = 'blue'>**类型 ... 类型名**</font> 表示可变长度的参数,本质是**数组* ...
- Nodejs内置中间件 第三方中间件 cookie和session
内置中间件 express也提供了好用的内置中间件,如提供一个静态资源管理的中间件,通过此中间件就可以帮助为我们快速搭建一个静态资源服务器 app.use(express.static('托管目录地址 ...
- 2024 Web 新特性 - 使用 Popover API 创建弹窗
Popover API 为开发者提供了一种声明式的方式来创建各种类型的弹窗.目前已在所有三大浏览器引擎中可用,并正式成为 Baseline 2024 的一部分. 一直以来,我们在实现弹出式菜单.提示框 ...
- kettle从入门到精通 第六十课 ETL之kettle for循环处理每条数据,so easy!
1.kettle原生是支持for循环处理的,无需通过javascript脚本或者java脚本开发for循环控制.当然如果想通过脚本挑战下也是可以的. 本节课主要讲解如何通过kettle中的job来实现 ...
- pytest系列之-mark功能的使用
功能使用: 标记用例,按正常.异常用例划分等级进行标记,或者按照模块进行划分. 标记后,可以执行部分用例. 例如: 你有以下用例,文件目录结构如下: testcase ----user ----man ...