首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 ># Event loop

# Event loop

作者头像
用户1175783
发布2019-09-10 14:54:28
1.6K0
发布2019-09-10 14:54:28
举报

[TOC]

​ dart是一种单线程语言,异步模型主要是通过事件轮询(event loop)来实现,另外也提供了更高级的Isolate来支持多线程,通常用于计算比较耗时的操作。

# Event loop

​ dart中的事件轮询包含两种事件队列:MicroTaskEventTask,其中经常使用的属于EventTask队列,MicroTask并不常用,也不推荐使用。

dart中的事件轮询看起来像这样:(摘自Flutter异步编程)

void eventLoop(){
    while (microTaskQueue.isNotEmpty){
     //执行MicroTask队列
    }

    if (eventQueue.isNotEmpty){
     //执行Event队列
    }
}

从上面代码可以看出来,每次事件轮询总是先执行完MicroTask中的事件。

# MicroTask(不推荐使用)

创建MicroTask有两种方法:

//第一种:使用全局静态方法创建
scheduleMicrotask((){
    print('this is a MicroTask demo');
});

//第二种:使用Future.microTask方法创建
 var result=await Future.microtask((){
    return "this is a MicroTask demo";
  });
  print(result);

​ 从使用API上可以看出使用Future.microtask的好处是允许我们有一个返回值(内部通过Future包裹实现),而scheduleMicrotask则不支持返回值。

# EventTask

​ 这是一种常用的事件队列,比如await/async,Timer,Future,Stream等,除了MicroTask之外的所有事件。

# await/async

async标记一个方法将要返回一个Future对象,该对象是可以被await的,dart中异步的一个重要标识就是await,每当遇到一个await时,dart都会等待awaitFuture执行完成后再执行后面的代码。

await/async只是用来简化Future的语法糖而已。

//如果你希望一个方法时异步执行的,首先它要有一个async标记
Future foot(int index) async{
    await Future.delayed(Duration(seconds: 1));
    print(index);
}
void main() async{
    print(1);
    //await可以让这个代码同步执行
    await foot(2);
    print(3);
    //没有await标记,代码将异步执行
    foot(4);
    print(5);
}

//下面时执行结果,是否符合你的预期:
1
2
3
5
4
# Timer定时器

​ Timer是dart中的定时器,支持立即(Timer.run()),延迟(Time()),间隔(Timer.periodic())3种执行方式。

​ 因为dart是单线程运行的所以Timer的执行也是需要在EventTask队列中排队执行的。下面这段代码演示Timer也要写入EventTask队列中才能运行:

import 'dart:async';

void main() async {
  //立即执行
  Timer.run(() {
    print('timer 0');
  });
  //延迟2s执行
  Timer(Duration(seconds: 2), () {
    print('timer 2');
  });
  var begin = DateTime.now();
  //使用循环延迟1s,
  //使用这种方式的好处是,一旦循环开始必须结束才会执行其它操作
  while (true) {
    var microseconds = DateTime.now().difference(begin).inMicroseconds;
    if (microseconds > 1000) {
      print('timer');
      break;
    }
  }
  //dart提供类sleep函数来提供等待功能
  sleep(Duration(seonds:1));
  //延迟1s
  Timer(Duration(seconds:1),(){
    print(('timer 1'));
  });
}

//执行结果:
timer
timer 0
timer 1
timer 2

代码开头我们定义了一个立即执行Timer,但是先执行的却是while代码块,说明Timer只是向事件循环中添加了一个任务,while代码块延迟1s,所以先被添加到事件循环的就是延迟1s的Timer,这也说明只有到了延迟时间才会将后续要执行的代码放进事件循环,而不是在定义的时候就放进去的。

# Future

FutureTimer的加强版本,一个Timer通常只处理一个无返回值的函数,Future对Timer进行了包装。Future是一个异步处理对象,所有的异步操作都返回一个Future对象,Future不是最终的返回值,只是一个异步状态值,你可以对一个Future对象使用await来等待异步操作完成。

Future()

//使用Future可以很容易的创建一个异步运行的匿名方法
var result=await Future((){
    print('返回一个bool值');
    return true;
});
print(result);

Future.delayed()

//延迟异步执行一个方法
result=await Future.delayed(Duration(seconds: 1),(){
    print('延迟返回一个bool值');
    return true;
});
print(result);

Future.wait()

//等待异步方法完成,wait可以保证所有的future都是按照顺序执行
//相当于:
// await future1;
// await future2;
// await future3;
var future1=Future.delayed(Duration(seconds: 5),(){
    return '第1个Future完成';
});
var future2=Future((){
    return '第2个Future完成';
});
var future3=Future.delayed(Duration(seconds: 1),(){
    return '第3个Future完成';
});
print('等待Futures完成');
var results =await Future.wait([future1,future2,future3]);
for (var item in results) {
    print(item);
}

Future.any()

//当任何一个future完成时结束
var anyFuture1=Future.delayed(Duration(seconds: 5),(){
    return '第一个Future';
});
var anyFuture2=Future((){
    return '第二个Future';
});
var anyFuture3=Future.delayed(Duration(seconds: 2),(){
    return '第3个Future';
});
print('等待最快完成的Future');
var item = await Future.any([anyFuture1,anyFuture2,anyFuture3]);
print(item);

Future.forEach()

//使用Future遍历Iterable<T>对象,
//下面对比普通的forEach与Future.forEach的区别
[3,2,1].forEach((item) async{
    await Future.delayed(Duration(seconds: item));
    print('forEach item $item');
});
//Future.forEach总是按顺序执行
await Future.forEach([3,2,1], (item) async{
    await Future.delayed(Duration(seconds: 1));
    print('Future.forEach item $item');
});

Future.doWhile()

//启动一个Future,直到返回值为false时结束
var index=0;
await Future.doWhile((){
    print('doWhile item ${index++}');
    return index!=10;
});

Future.sync

//直接执行sync中传递的方法,始终返回一个Future
//下面的代码可以看到返回结果始终时一个Future
var syncResult1=await Future.sync((){
    return "无async标记";
});
print(syncResult1);
var syncResult2=await Future.sync(() async{
    return '有async标记';
});
print(syncResult2);

Future.microtask()

//创建一个MicroTask任务
Future.microtask((){});

Future.value()

//从值对象构造一个Future
var future=await (){
    //等价:Future.sync(()=>'future执行结果');
    return Future.value('future执行结果');
}();
print(future);

Future.error()

//创建一个错误返回值的Future
var failedFuture=await (){
    	return Future.error('创建一个错误返回值的Future');
    }();
    print(failedFuture);
}
# Stream

下面这张图演示了Stream的运行原理:

# MicroTask与EventTask的执行顺序对比:

下面有两段官方提供的代码足以搞懂他们的区别:

  1. https://dart.dev/articles/archive/event-loop#question-1
  2. https://dart.dev/articles/archive/event-loop#question-2

# Isolate

dart是一个单线程程序,在执行耗时的操作是会导致线程卡住,尤其在Flutter上会导致ui卡顿。

isolate优点是将耗时的代码放在一个独立的线程中执行,缺点是不能共享其它线程的实例成员,有点类似进程间的数据隔离。

import 'dart:async';
import 'dart:io';
import 'dart:isolate';

computer(SendPort port) async {
  var receivePort = ReceivePort();
  // 向client暴漏自己的可通信对象
  port.send(receivePort.sendPort);
  Future(() async {
    //监听client消息
    await for (var data in receivePort) {
      print(data);
      sleep(Duration(seconds: 1));
      port.send(++data);
    }
  });
}

main(List<String> args) async {
  var receivePort = ReceivePort();
  // isolate要求第一个参数不能是匿名方法
  // 如果将第一个参数作为server端,那么第二参数就是客户端,server端通过这个参数来与client端交互
  await Isolate.spawn(computer, receivePort.sendPort);
  var stream = receivePort.asBroadcastStream();
  // 接收server端的可通信对象,用于发送数据
  SendPort sendPort = await stream.first;
  // 发送一个数据
  sendPort.send(0);
  Future(() async {
    // 监听收到的server端消息
    await for (var data in stream) {
      print(data);
      sleep(Duration(seconds: 1));
      sendPort.send(++data);
    }
  });
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • # Event loop
    • # MicroTask(不推荐使用)
      • # EventTask
        • # await/async
        • # Timer定时器
        • # Future
        • # Stream
      • # MicroTask与EventTask的执行顺序对比:
      • # Isolate
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档