前言

貌似关于Dart的文章没流量啊,就算在小编关怀上了首页,看得人还是很少的。

算了,今天持续发烧,再来写写如何使用 Dart 语言的并发操作。说起并发操作,玩 Go 的同学该笑了,这就是我们的看家本领啊。玩 PHP 的同学继续看看,表示我们光看不说话。

代码演示之前,我们先假设一个场景。假设我有一些漂亮妹妹,他们要出门旅行了,旅行的时候会发照片给我。在这里个过程中,代码需要做的事情:

  1. 接收请求
  2. 安排出行计划,同时出行哦,不能有先后之分
  3. 他们各自出行,可以发照片给我
  4. 返回结果

这个过程中,我关心的是他们能不能处理好自己的事情,因为我妹妹太多了,如果都让我帮他们,累死我也搞不定啊,我就干两件事,安排好出行计划,最后收照片。

代码演示一下吧

import 'dart:io';
import 'dart:isolate'; main() async {
print(DateTime.now().toString() + ' 开始'); //这是一个接收端口,可以理解成我的手机
ReceivePort receivePort = new ReceivePort(); //安排三个妹妹出去旅行,让她们牢记我的手机号
await Isolate.spawn(travelToBeijing, receivePort.sendPort);
await Isolate.spawn(travelToShanghai, receivePort.sendPort);
await Isolate.spawn(travelToGuangzhou, receivePort.sendPort); //我就在手机上,等待他们的消息
receivePort.listen((message) {
print(message);
}); print(DateTime.now().toString() + ' 结束');
} void travelToBeijing(SendPort sendPort) {
sleep(Duration(seconds: 3));
sendPort.send(DateTime.now().toString() + ' 我是妹妹1,我在北京了');
} void travelToShanghai(SendPort sendPort) {
sleep(Duration(seconds: 3));
sendPort.send(DateTime.now().toString() + ' 我是妹妹2,我在上海了');
} void travelToGuangzhou(SendPort sendPort) {
sleep(Duration(seconds: 3));
sendPort.send(DateTime.now().toString() + ' 我是妹妹3,我在广州了');
}

上面写了那么多,都是啥意思呢,我自己稍微解释下上面的代码。

Dart 里的并发,用到的是 Isolate 类。

Isolate 翻译过来即是 隔离区, 是 Dart 实现并发的重要类。它并发的原理,既不是多进程,也不是多线程,你说类似于 Go 的协程吧,也不像。

真的很难定义它,期待对操作系统研究更深的同学来布道,当然这不影响我们使用。

Isolate.spawn 来定义一个并发任务,接收两个参数,第一个是该任务的处理函数,第二个是该处理函数的所需要的参数

ReceivePort 翻译一下 接收端口, 也可以翻译成 接收器,用来接收各个任务回传的消息。

receivePort.listen 用来监听各任务的回传信息,代码里只是简单打印

执行它,得到打印的结果

2021-07-01 15:40:38.132122 开始
2021-07-01 15:40:38.295683 结束
2021-07-01 15:40:41.200316 我是妹妹1,我在北京了
2021-07-01 15:40:41.248851 我是妹妹2,我在上海了
2021-07-01 15:40:41.296737 我是妹妹3,我在广州了

注意看打印结果,妹妹们很乖,基本在同一时间给我回复了消息。总共时间差不多3秒钟,你可以添加更多任务,都会是3秒钟。

再次封装一下

实际使用的时候,我们可以再次封装,使用的同学不用去想 Isolate, ReceivePort 都是什么鬼

import 'dart:io';
import 'dart:isolate'; class MultiTask {
static void run(
{List<TaskItem> taskList,
Function taskFunc,
Function onCompletedItem,
Function onCompletedAll}) async {
ReceivePort receivePort = new ReceivePort(); Map<String, Isolate> mapParam = {};
for (int i = 0; i < taskList.length; i++) {
TaskItem taskItem = taskList[i];
mapParam[taskItem.key] = await Isolate.spawn(
taskFunc, TaskMessage(receivePort.sendPort, taskItem));
} List<TaskRes> taskResList = [];
receivePort.listen((message) async {
TaskRes taskRes = message as TaskRes;
if (null != onCompletedItem) await onCompletedItem(taskRes);
taskResList.add(taskRes);
mapParam[taskRes.key].kill();
if (taskResList.length == taskList.length) {
receivePort.close();
if (null != onCompletedAll) await onCompletedAll(taskResList);
}
});
}
} class TaskMessage {
SendPort sendPort;
TaskItem taskItem;
TaskMessage(this.sendPort, this.taskItem);
} class TaskItem {
String key;
String param; TaskItem(this.key, this.param);
} class TaskRes {
String key;
String res; TaskRes(this.key, this.res);
}

使用的时候,这样来:

import 'dart:io';
import 'dart:isolate';
import 'MultiTask.dart'; main() async {
List<TaskItem> taskList = [
TaskItem('1', 'param1'),
TaskItem('2', 'param2'),
TaskItem('3', 'param1'),
TaskItem('4', 'param2'),
TaskItem('5', 'param1'),
TaskItem('6', 'param2'),
TaskItem('7', 'param1'),
TaskItem('8', 'param2'),
TaskItem('9', 'param1'),
TaskItem('0', 'param2'),
]; print(DateTime.now()); MultiTask.run(
taskList: taskList,
taskFunc: taskFunc,
onCompletedItem: (TaskRes taskRes) =>
print(DateTime.now().toString() + '_' + taskRes.res),
onCompletedAll: (List<TaskRes> taskResList) =>
print(DateTime.now().toString() + '_onCompletedAll'),
);
} void taskFunc(TaskMessage taskMessage) async {
sleep(Duration(seconds: 3)); String res = 'onCompletedItem is ok'; taskMessage.sendPort.send(TaskRes(taskMessage.taskItem.key, res));
}

走起来吧

2021-07-01 15:50:54.862973
2021-07-01 15:50:57.924675_onCompletedItem is ok
2021-07-01 15:50:57.954982_onCompletedItem is ok
2021-07-01 15:50:57.986042_onCompletedItem is ok
2021-07-01 15:50:58.021282_onCompletedItem is ok
2021-07-01 15:50:58.053387_onCompletedItem is ok
2021-07-01 15:50:58.088492_onCompletedItem is ok
2021-07-01 15:50:58.121968_onCompletedItem is ok
2021-07-01 15:50:58.157117_onCompletedItem is ok
2021-07-01 15:50:58.190835_onCompletedItem is ok
2021-07-01 15:50:58.229044_onCompletedItem is ok
2021-07-01 15:50:58.241011_onCompletedAll

可以看到,中间每一个任务完成的时间,都很接近,并发处理很完美

总结

当需要处理很多任务时,可以开辟多个隔离区,并发执行,提高效率。

Dart语言对并发的处理,还算人性化,理解起来没有难度,用起来也容易。

同学们,骚起来吧。

持续发烧,聊聊Dart语言的并发处理,能挑战Go不?的更多相关文章

  1. Dart语言入门(一)

    Dart 语言介绍 Dart 是谷歌在 2011 年推出的编程语言,是一种结构化 Web 编程语言,允许用户通过 Chromium 中所整合的虚拟机(Dart VM)直接运行 Dart 语言编写的程序 ...

  2. Dart 语言简易教程系列

    google Fuchsia系统 及 dart语言简介 在 InteIIiJ IDEA 中搭建 Dart 的开发环境 Dart Linux 开发环境搭建 Dart 语言简易教程(一) Dart 语言简 ...

  3. Dart语言特性必备了解!

    学习Dart语言,必须将以下的概念熟记于心: 在dart语言中,一切皆为对象.所有的对象都是一个类的实例.甚至整数.函数.null也看做是对象.所有的对象都继承于Object类 尽管Dart是强类型语 ...

  4. Dart语言快速学习上手(新手上路)

    Dart语言快速学习上手(新手上路) // 声明返回值 int add(int a, int b) { return a + b; } // 不声明返回值 add2(int a, int b) { r ...

  5. 红黑树的删除详解与思路分析——不同于教科书上的算法(dart语言实现)

    对于红黑树的删除,看了数据结构的书,也看了很多网上的讲解和实现,但都不满意.很多讲解都是囫囵吞枣,知其然,不知其所以然,讲的晦涩难懂. 红黑树是平衡二叉树的一种,其删除算法是比较复杂的,因为删除后还要 ...

  6. Dart 语言了解

    Dart 语言了解 概念 当您了解Dart语言时,请记住以下事实和概念: 您可以放在变量中的所有内容都是一个对象,每个对象都是一个类的实例.偶数,函数和 null对象.所有对象都从Object类继承. ...

  7. 30分钟掌握Dart语言

    在Dart中,一切都是对象,一切对象都是class的实例,哪怕是数字类型.方法甚至null都是对象,所有的对象都是继承自Object 虽然Dart是强类型语言,但变量类型是可选的因为Dart可以自动推 ...

  8. 简单易懂的Dart》 - Dart语言中文简明教程

    转自:https://www.blackglory.me/straightforward-dart/ Dart是Google公司发布的网络编程语言,其诞生的目的是为了让广大C类OOP程序员们克服Jav ...

  9. Atitit.dart语言的特性  编译时js语言大总结

    Atitit.dart语言的特性  编译时js语言大总结 1. 原型环境1 1.1. Dart可以编译js3 2. 第二个期待的理由是Dart的语言特性,没有什么特别特性好像,类似java c#一小时 ...

  10. Flutter学习笔记(2)--Dart语言简介

    Dart简介: Dart诞生于2011年10月10日,Dart是一种"结构化的web编程"语言,Dart虽然是谷歌开发的计算机编程语言,但后来被ECMA认定位标准,这门语言用于We ...

随机推荐

  1. 使用logstash读取MySQL数据传输到es,并且@timestamp字段采用MySQL中的字段时间--建议采用这个

    MySQL中数据样式 ES中数据样式 input { jdbc { jdbc_connection_string => "jdbc:mysql://192.168.0.145:3306 ...

  2. Redis的web管理界面redis-manager

    下载 下载地址:https://github.com/ngbdf/redis-manager/releases 配置 tar -zxv -f redis-manager-2.3.2.2-RELEASE ...

  3. [题解] Codeforces 1720 E Misha and Paintings 结论

    题目 算是诈骗题? 令一开始就存在的颜色数为cnt.k>=cnt的情况,显然每次找一个出现不止一次的颜色,然后把这个颜色的恰好一个方块替换成一种没有出现过的颜色就可以了,\(k-cnt\)次解决 ...

  4. PHP全栈开发(八):CSS Ⅹ 导航栏制作

    学习了这么久的CSS,我们现在也可以小试牛刀一下了,我们使用我们学会的CSS知识来制作一个导航栏. 我们都知道,在现代的导航栏里面,最普遍的就是使用无序列表来制作导航栏. 我们可以使用如下代码来制作一 ...

  5. 2022牛客OI赛前集训营-提高组(第一场) 奇怪的函数 根号很好用

    奇怪的函数 考虑暴力,每次查询\(O(n)\)扫所有操作,修改\(O(1)\) 这启发我们平衡复杂度,考虑分块. 观察题目性质,可以发现,经过若干次操作后得到的结果一定是一个关于\(x\)的分段函数, ...

  6. pthread_mutex_t & pthread_cond_t 总结

    pthread_mutex_t & pthread_cond_t 总结 一.多线程并发 1.1 多线程并发引起的问题 我们先来看如下代码: #include <stdio.h> # ...

  7. linux安装达梦数据库8

    PS.本次测试只是为了项目需要,但是在部署和启动程序的时候发生了一系列的报错,由此记录下来为日后作参考 安装达梦数据库 1. 达梦数据库(DM8)简介 达梦数据库管理系统是武汉达梦公司推出的具有完全自 ...

  8. Oracle数据库的两种授权收费方式介绍!

    首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...

  9. 【FAQ】关于华为地图服务定位存在偏差的原因及解决办法

    一. 问题描述: 华为地图服务"我的位置"能力,在中国大陆地区,向用户展示他们在地图上的当前位置与用户的实际位置存在较大的偏差. 具体差别可以查看下方的图片: 二. 偏差较大的原因 ...

  10. 死磕Java面试系列:深拷贝与浅拷贝的实现原理

    深拷贝与浅拷贝的问题,也是面试中的常客.虽然大家都知道两者表现形式不同点在哪里,但是很少去深究其底层原理,也不知道怎么才能优雅的实现一个深拷贝.其实工作中也常常需要实现深拷贝,今天一灯就带大家一块深入 ...