node是多线程吗,node js 多线程
为什么Node.js不是完全单线程的?怎么理解?下面这篇文章就带你探讨一下,希望能帮到你!
node.js速度课程简介:进入学习
相信大家都知道node是单线程程序,利用事件循环可以实现多个并发。不幸的是,这并不完全正确。
那么Node.js为什么不是完全单线程的程序呢?
Node.js 是单线程的程序*
我们自己所有的Javsacript,V8,EventLoop都运行在同一个线程里,也就是主thrad。
哎,这不就是说node是单线程的吗?
但是可能你不知道node里面有很多模块背后都是C代码。
虽然node没有给用户控制线程的权限,但是C可以使用多线程。
那么node什么时候会用多线程呢?
如果一个节点方法调用后面C的同步方法,都是在主线程内部运行。
如果一个节点方法调用了后面C的异步方法,有时它并不在主线程内部运行。
同步方法,跑在 main thread 里面
这里的密码相关模块,很多都是c写的,下面这个程序是一个计算hash的函数,一般用来存储密码。
从“crypto”导入{ pbk df 2 sync };
const start time=date . now();
设索引=0;
for(索引=0;指数3;索引){
pbkdf2Sync(秘密,盐,100000,64, sha 512 );
const end time=date . now();
console.log(`${index} time,$ { end time-start time } `);
}
const end time=date . now();
console . log(` in the end `);输出时间,
0时间,44
1次,90
2次,134
最后你可以看到每次大概用了~45ms,代码主线程是顺序执行的。
异步 pbkdf2 方法,不跑在 main thread 里面
从“操作系统”导入{ CPU };
从“crypto”导入{ pbk df 2 };
console . log(CPU()。长度);
let start time=console . time( time-main-end );
for(设索引=0;指数4;索引){
start time=console . time(` time-$ { index } `);
pbkdf2(secret ,` salt${index} `,100000,64, sha512 ,(err,derivedKey)={
if(err)throw err;
console . time end(` time-$ { index } `);
});
}
console . time end( time-main-end );输出时间,
时间-主要-结束:0.31毫秒
时间-2分45秒646秒
时间-0分46.055秒
时间-3分46.846秒
Time-1: 47.159ms这里主线程结束的比较早,但是,每次计算的时间是45ms,要知道一个cpu计算hash的时间是45ms,这里node肯定是用多线程进行hash计算的。
如果我在这里把调用次数改为10,那么时间如下。可以看出,随着CPU核心数的用完,时间也在增加。再次证明node绝对使用多线程进行哈希计算。
时间-主要-结束:0.451毫秒
时间-1分44.977秒
时间-2分46.069秒
时间-3分50秒033秒
时间-0分51秒381秒
时间-5: 96.429ms //这里注意,从第五次开始就增加了
时间-7分101.61秒
时间-4分113.535秒
时间-6分121.429秒
时间-9分151.035秒
时间-8: 152.585ms虽然这里证明了,node绝对启用了多线程。但是有个小问题?我电脑的CPU是AMD R5-5600U,6核12线程。但是为什么从第五次开始时间增加了呢?node没有充分利用我的CPU?
原因是什么?
节点使用预定义的线程池,其默认大小为4。
让我们看一个例子,
HTTP request
从“https”导入{ request };
常量选项={
主机名: www.baidu.com ,
端口:443,
路径:/img/PC _ 7 AC 6 a6 d 319 ba 4 AE 29 b 38 E5 e 4280 e 9122 . png ,
方法:“GET”,
};
let start time=console . time(` main `);
for(设索引=0;指数15;索引){
start time=console . time(` time-$ { index } `);
const req=request(options,(res)={
console . log(` status code:$ { RES . status code } `);
console . time end(` time-$ { index } `);
res.on(data ,(d)={
//process . stdout . write(d);
});
});
req.on(错误,(错误)={
console.error(错误);
});
req . end();
}
console . time end( main );主:13.927毫秒
时间-2:83.247毫秒
时间-4分89.641秒
时间-3分91.497秒
时间-12分91.661秒
时间-5分94.677秒
.
时间-8分134.026秒
时间-1分143.906秒
时间-13:140.914毫秒
Time-10: 144.088ms这里,主程序也提前结束了。在这里,我启动了15次http请求下载图片,他们花费的时间并没有成倍增长。似乎并没有受到线程池/cpu的影响。
为什么?节点是否正在使用线程池?
如果C的异步方法在Node后面,它会首先尝试是否有内核异步支持。比如这里,网络要用epoll (Linux)。如果内核不提供异步模式,节点将使用自己的线程池。
因此,虽然http请求是异步的,但它是由内核实现的。内核完成后,会通知C,C会通知主线程处理回调。
那么Node的哪些异步方法会使用线程池呢?哪些不会?
本机内核异步
TCP/UDP服务器客户端Unix域套接字(IPC)管道pipesdns.resolveXXXtty输入(stdin等)Unix信号子进程线程池
Fs。*dns.lookuppipe (edge case)这也是大多数节点优化的起点。
但是这些怎么和最重要的事件循环结合呢?
Event Loop
相信大家对Event loop都很熟悉。事件循环就像一个分配器,
如果遇到普通的javascript程序或者回调,就交给V8吧。
如果同步方法后面是C写的,就交给C,在主线程上运行。
如果异步方法后面是C写的,如果有内核异步支持,就从主线程交给内核。
如果异步方法的后面是C写的,如果没有内核异步支持,就会从主线程交给线程池。
如果线程池和内核有结果,它们会将结果返回给事件循环。如果注册了javascript回调,就交给V8处理。
然后循环,直到没什么可处理的。
所以 Node 不完全是单线程程序。
更多关于node的信息,请访问:nodejs教程!就这样理解Node.js不是一个完整的单线程程序(分析)。更多详情请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。