JavaScript单线程事件循环及多线程实现

一、JavaScript的单线程特点

JavaScript最初设计是用来在浏览器中操作DOM的,所以JavaScript的单线程特点也是为了避免多线程时带来的同步问题。

二、JavaScript单线程事件循环

JavaScript单线程事件循环特点如下

  • JavaScript是单线程的,这个线程中拥有唯一的一个事件循环
  • JavaScript 代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。
  • 一个线程中,事件循环是唯一的,但是任务队列可以拥有多个
  • 任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
    • 同步任务:指在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
    • 异步任务:指不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程某个异步任务可以执行了,该任务才会进入主线程执行。
  • 任务队列又分为macro-task(宏任务)与micro-task(微任务),它们被分别称为taskjobs
  • macro-task包括如下六个部分:
    • script(整体代码),
    • setTimeout,
    • setInterval,
    • setImmediate,
    • I/O,
    • UI rendering。
  • micro-task包括如下四个部分:
    • process.nextTick,
    • Promise,
    • Object.observe(已废弃),
    • MutationObserver(html5新特性)。
  • setTimeout/Promise等我们称之为任务源,而进入任务队列的是他们指定的具体执行任务
  • 来自不同任务源的任务会进入到不同的任务队列。其中setTimeoutsetInterval同源的
  • 事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环
    • 之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。
  • 其中每一个任务的执行,无论是macro-task还是micro-task,都是借助函数调用栈来完成。

三、例子

setTimeout(function () {
  console.log('timeout1');
})

new Promise(function (resolve) {
  console.log('promise1');
  for (var i = 0; i < 1000; i++) {
    i == 99 && resolve();
  }
  console.log('promise2');
}).then(function () {
  console.log('then1');
})

console.log('global1');

上面代码的执行顺序是什么?

1. 代码执行遇到setTimeout,setTimeout为一个宏任务源,那么他的作用就是将任务分发到它对应的队列中。
2. script执行时遇到Promise实例。Promise构造函数中的第一个参数,是在new的时候执行,因此不会进入任何其他的队列,而是直接在当前任务直接执行了,而后续的.then则会被分发到micro-task的Promise队列中去。 因此输出:promise1、promise2。
3. script任务继续往下执行,最后只有一句输出了globa1,然后,全局任务就执行完毕了。
4. 第一个宏任务script执行完毕之后,就开始执行所有的可执行的微任务。这个时候,微任务中,只有Promise队列中的一个任务then1,因此直接执行就行了,执行结果输出then1。
5. 当所有的micro-tast执行完毕之后,表示第一轮的循环就结束了。这个时候就得开始第二轮的循环。第二轮循环仍然从宏任务macro-task开始。这个时候,我们发现宏任务中,只有在setTimeout队列中还要一个timeout1的任务等待执行。因此就直接执行即可。
所以输出是这样的:

promise1
promise2
global1
then1
timeout1

四、JavaScript多线程的实现

test.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>JavaScript Multiple Processes Test</title>
</head>

<body>
  <input type="text" name="haorooms" id="haorooms" value="" />
  <button id="start">start</button>
  <button id="stop">stop</button>
  <button id="ale">alert</button>
  <script type="text/javascript">
    var haorooms = document.getElementById("haorooms"),
        stop = document.getElementById("stop"),
        start = document.getElementById("start"),
        ale = document.getElementById("ale"),
        worker;
    stop.addEventListener("click", function () {
      //用于关闭worker线程
      worker ? worker.terminate() : {};
    });
    start.addEventListener("click", function () {
      //开起worker线程
      worker = new Worker("test.js");
      worker.onmessage = function () {
        haorooms.value = event.data;
      };
    });
    ale.addEventListener("click", function () {
      alert("i'm a alert worker test");
    });
  </script>
</body>

</html>

test.js

var i = 0;
function mainFunc(){
    i++;
    //把i发送到浏览器的js引擎线程里
    postMessage(i);
}
var id = setInterval(mainFunc,1000);

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343