深度理解nodejs[2]-事件循环

发布时间:2020-07-14 19:54:26 作者:jonson_jackson
来源:网络 阅读:174

进程与线程

我们在电脑中会运行多个程序,每一个程序中都会有多个线程。
例如我们运行比特币客户端的时候,我们某一个线程要处理网络、某一个线程要处理挖矿、某一个线程要处理用户输入…
线程的调度使用了操作系统级别的调度器来明确了哪一个线程应该被执行。线程也有优先级之分,例如监听鼠标滑动的优先级就会很高,因为其不能等待太长的时间。

为了在给定的时间内更快更多的处理线程:
1、我们可以通过增加CPU的核心数量或者是
2、调度器当监测到线程中运行中断,如读取文件网络时,及时切换到其他的线程中执行。

事件循环

nodejs是单线程的事件循环机制
伪代码演示事件循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const peningTimers =[];
const pendingOSTasks=[];
cosnt pendingOperations=[];

1、初始化
myfile.runContent()

function shouldContinue(){ //是否继续
 1、检查setTimeOut、setInterval、setImmediate
 2、检查是否有监听端口等操作系统级别的任务
 3、检查是否有文件、网络等长期的操作
return peningTimers.length || pendingOSTasks.length || pendingOperations.length;
}

2、事件循环
while(shouldContinue()){
//1.观察peningTimers.length,是否调查setTimeOut、setInterval等函数
//2、观察pendingOSTasks.length   pendingOperations.length,并调用相关回调函数
//3.暂停、一直等到上面的某一个事件完成
//4、调用setImmediate等函数
//5、处理close事件
}

3、退出

nodejs的单线程与多线程

nodejs的单线程,是对于其处理事件循环来讲的,有了事件触发,就会执行相应函数。没有事件触发,就会等待。从这个意义上来说,nodejs是单线程的。
但是在处理具体的任务,函数的时候。nodejs确是多线程的。

nodejs的单线程与多线程证明

1
2
3
4
5
6
7
const crypto = require('crypto');

const start = Date.now();

crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('1:',Date.now()-start);
});

测试pbkdf2速度:1: 868

1
2
3
4
5
6
7
8
9
10
11
const crypto = require('crypto');

const start = Date.now();

crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('1:',Date.now()-start);
});

crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('2:',Date.now()-start);
});

测试pbkdf2速度:

1
2
1: 891
2: 893

说明了pbkdf2函数是多线程来执行的。libuv中默认有4个线程,pbkdf2函数正是借助libuv实现了多线程。

测试libuv中默认有4个线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const crypto = require('crypto');

const start = Date.now();

crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('1:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('2:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('3:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('4:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('5:',Date.now()-start);
});
1
2
3
4
5
4: 919
1: 922
3: 936
2: 936
5: 1813

注意,明显第5个线程时间增加了一倍,因为默认libuv中默认有4个线程,第5个线程陷入了等待。

修改libuv中默认默认线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
process.env.UV_THREADPOOL_SIZE = 5;

const crypto = require('crypto');

const start = Date.now();

crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('1:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('2:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('3:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('4:',Date.now()-start);
});
crypto.pbkdf2('a','b',100000,512,'sha512',()=>{
 console.log('5:',Date.now()-start);
});

测试速度:

1
2
3
4
5
1: 956
5: 963
3: 970
2: 971
4: 974

http库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const https = require('https');
const start = Date.now();

function dorequest(){
 https.request('https://www.baidu.com',res=>{
   res.on('data',()=>{});
   res.on('end',()=>{
     console.log(Date.now()-start);
   });
 })
 .end();
}
dorequest();
dorequest();
dorequest();
dorequest();
dorequest();
dorequest();
dorequest();
dorequest();
dorequest();

测试速度:

1
2
3
4
5
6
7
8
9
48
50
52
53
54
55
57
58
62

https网络访问,调用了操作系统资源,libuv只是起到了代理的作用,所以不收到libuv默认4个线程的限制。

总结

pbkdf2等函数是借助libuv实现多线程的。但是当这些函数执行完毕后,会触发完成事件.nodejs主线程触发事件的处理却是单线程的。

深度理解nodejs[2]-事件循环

推荐阅读:
  1. 以太坊如何计算交易成本
  2. BUTXO详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

区块链 nodejs 前端

上一篇:Hikari 数据库连接池配置详解

下一篇:live555 testrtspclient客户端建立rtp over tcp 异常问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》