协程,英文名coroutine,是一种执行过程可以被暂停和恢复的方法。各个协程之间相互协作完成一个任务。

让我们来看一个关于发挥协程作用的例子。假定我们有一个生产者和消费者的关系,生产者创建物品并将物品添加到一个队列,消费者从队列中取出物品并使用该物品。为了提高效率,生产者会一直创建并添加物品,直到队列满为止,队列满时通知运行环境调用消费者;消费者会一直取出并使用物品,直到队列空为止,队列空时通知运行环境调用生产者。下面是使用协程实现这个关系的伪代码:

  1. var q := new queue
  2. coroutine produce
  3. loop
  4. while q is not full
  5. create some new items
  6. add the items to q
  7. yield to consume
  8. coroutine consume
  9. loop
  10. while q is not empty
  11. remove some items from q
  12. use the items
  13. yield to produce

在这段代码中,produce和consume不是普通的方法,而是由关键字coroutine被定义成为协程。当运行环境执行produce时,produce会在队列满时通过yield主动放弃执行权,并告知运行环境去调用consume协程。同样,consume协程在队列空时也会通过yield主动放弃执行权,并告知运行环境去调用produce协程。

在介绍什么是协程之后,接下来我将讲协程在ES6中的实现方式。ES6提供了一种新的方法名叫Generator。Generator的执行过程可以被暂停和恢复,所以它被认为是ES6中的协程,但严格地说,Generator只是半协程(semi-coroutine),因为虽然它可以主动放弃执行权,但是它并没有告知运行环境,下一步哪个协程会被调用。当一个Generator被调用时,它的代码并不会被执行,调用者得到的是它的观察者(Observer)。调用者通过调用这个观察者的方法,比如next方法,来执行Generator的代码。

下面是通过Generator实现上述生产者和消费者关系的ES6代码:

  1. const Q = [];
  2. const Q_LEN = 10;
  3.  
  4. function* produce() {
  5. while (Q.length < Q_LEN) {
  6. const item = Date.now();
  7. Q.push(item);
  8. console.log(`Item ${item} is produced`);
  9.  
  10. if (Q.length === Q_LEN) {
  11. yield;
  12. }
  13. }
  14. }
  15.  
  16. function* consume() {
  17. while (Q.length > 0) {
  18. const item = Q.pop();
  19. console.log(`Item ${item} is consumed`);
  20.  
  21. if (Q.length === 0) {
  22. yield;
  23. }
  24. }
  25. }
  26.  
  27. function bootstrap() {
  28. const producer = produce();
  29. const consumer = consume();
  30.  
  31. while(true) {
  32. producer.next();
  33. consumer.next();
  34. }
  35. }
  36.  
  37. bootstrap();

在上面代码中,produce和consume是两个协程。bootstrap方法是这两个协程的调用者,它首先获取produce和consume协程的观察者,然后循环调用观察者的next方法,从而使得生产者和消费者的关系持续运行。在循环过程中,如果produce检测队列已满,它就主动放弃执行权从而被暂停,consume将获得执行权,如果consume检测队列已空,它就主动放弃执行权从而被暂停,produce将重新获得执行权。

好了,上文简单介绍了什么是协程及其在ES6中的实现方式,希望它能对在理解协程和在ES6中使用协程产生疑问的人有所帮助,谢谢。

参考

  • https://en.wikipedia.org/wiki/Coroutine

简单介绍什么是协程及其在ES6中的实现方式的更多相关文章

  1. 协程在Web服务器中的应用(配的图还不错)

    协程(纤程,微线程)这个概念早就有之,各家互联网公司也都有研究,但在国内各大论坛和大会热起来,还是今年的事. 最近参与讨论开放平台建设和架构设计过程中,有同事提到了使用协程代替线程,能够很大幅度的提高 ...

  2. [转]Unity3D协程介绍 以及 使用

    作者ChevyRay ,2013年9月28日,snaker7译  原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协 ...

  3. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  4. Unity3D协程介绍 以及 使用

    作者ChevyRay ,2013年9月28日,snaker7译  原文地址:http://unitypatterns.com/introduction-to-coroutines/ 在Unity中,协 ...

  5. Python中异步协程的使用方法介绍

    1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...

  6. 带你简单了解python协程和异步

    带你简单了解python的协程和异步 前言 对于学习异步的出发点,是写爬虫.从简单爬虫到学会了使用多线程爬虫之后,在翻看别人的博客文章时偶尔会看到异步这一说法.而对于异步的了解实在困扰了我好久好久,看 ...

  7. Unity3D 协程的介绍和使用

    我是快乐的搬运工 http://blog.csdn.net/u011397120/article/details/61236055 ---------------------------------- ...

  8. spawn协程学习

    对于IO密集型的程序,一般比较高效的做法是选择异步来实现,因为使用异步的方法更容易写出高效的程序.然而使用异步的话,经验较少的人往往会使自己的程序结构变得很混乱,进而导致程序的可读性变差.记得有人说过 ...

  9. [转载]Python 3.5 协程究竟是个啥

    http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...

随机推荐

  1. vue-cli 如何配置sass

    第一步:安装对应的node模块 npm install node-sass --save-dev npm install sass-loader --save-dev 第二步:在webpack.bas ...

  2. redis在spring-boot中的应用

    Redis(REmote DIctionary Server) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redis是一个开源的使用ANSI C语言编写.遵守BS ...

  3. ORACLE 错误代码提示归集

    有时数据库出现问题,不是每次都有网络可查,所以把所有的ora系列的错误整理出来, 在最没有办法的时候,需要自己来解决,有了这些根据,问题会好办的.虽说对于数据库方面, DBA很强大,他们在遇到错误时, ...

  4. c# winform treelistview的使用(treegridview)

    TreeView控件显示的内容比较单一,如果需要呈现更详细信息TreeListView是一个不错的选择. 先看效果: 首先需要引用文件System.Windows.Forms.TreeListView ...

  5. 小程序采坑系列-this.setData

    今天踩了大坑,坑里还都是碎瓶渣子.. 先说一下基本使用.官网也有. 比如说你在main.js里面有这些变量.想修改某些值. data: { main_view_bgcolor: "" ...

  6. python网络编程之单线程之间的并发

    单线程之间的并发就是利用一个线程实现并发的效果,也就是利用了cup遇到阻塞的那段时间去做别的事情,从而提高了cup的利用率,使之在单个线程中就实现了并发的效果. 下面就是一个简单的服务端单个线程实现并 ...

  7. java桌面程序打包教程

    首先打包成j可执行的jar文件. . 接下来找到自己生成jar文件的路径就可以看到jar文件了,我的是在桌面: 在桌面新建一个文件夹(名字随便取,一般去项目名字) 上面是我取的文件夹名字,然后把资料文 ...

  8. Nginx日志切割案例讲解,Nginx的知识讲解

    Nginx 是一个非常轻量的 Web 服务器,体积小.性能高.速度快等诸多优点.但不足的是也存在缺点,比如在产生的访问日志文件一直就是一个,不会自动地进行切割,如果访问量很大的话,将会导致日志文件容量 ...

  9. Lucene.net(4.8.0)+PanGu分词器问题记录一:分词器Analyzer的构造和内部成员ReuseStategy

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  10. jquery写的树状列表插件-alvintree

    在做项目的时候遇到选择部门下人员的功能,可多选可单选,所以就想着使用树状列表来进行选择,但在网上找了很多,发现要么就是挺复杂,要么就是需要各种前端框架的支持,试了一个感觉难用,所以就想着自己写一个简便 ...