当前位置: 首页 > 后端技术 > Node.js

Node.js多线程

时间:2023-04-04 00:37:44 Node.js

随着10.5.0的发布,Node.js添加了对多线程的实验性支持(worker_threads模块)。为什么需要多线程?由于Node.js是单线程执行JS,CPU密集型计算任务可能会使主线程忙碌,从而影响服务的性能。虽然可以通过child_process模块??创建子进程来解决,但是一方面进程之间不能共享Memory,另一方面创建进程的开销也不小。因此,在10.5.0版本中,Node.js提供了worker_threads模块来支持多线程。长期以来对其不擅长CPU密集型计算的批评有望成为历史。如何启用多线程?多线程还在实验阶段,所以需要在启动时加上--experimental-workerflag才能生效。如何创建多线程?worker_threads模块中的几个重要类:MessageChannel:用于创建用于异步、双向通信的通道实例。MessageChannel实例包含两个属性port1和port2,它们都是MessagePort的实例。MessagePort:用于表示MessageChannel通道的终端,用于Worker之间传输结构化数据、内存区域等MessagePort。MessagePort继承了EventEmitter,因此可以使用postMessage和on方法来发送和接收消息。Worker:用来创建一个独立的JS线程。worker_threads模块中的几个重要属性:parentPort:子线程中的parentPort指向可以与主线程通信的MessagePort。子线程向父线程发送消息parentPort.postMessage(...)子线程从父线程接受消息parentPort.on('message',(msg)=>...)isMainThread:用于区分当前文件是否在主线程中ExecuteworkerData:用于将数据的副本传递给Worker构造函数。在子线程中,可以通过workerData获取到父进程传入的数据。了解了常用的类和属性后,我们来看一下代码示例:'兰德尔'}});w.postMessage(1e10);conststartTime=Date.now();w.on('message',function(msg){console.log('主线程获取消息:'+msg);console.log('计算时间:'+(Date.now()-startTime)/1000);});console.log('主线程执行');}else{constlongComputation=(val)=>{让总和=0;for(leti=0;i{console.log(`${workerData.name}workergetmessage:`+msg);parentPort.postMessage(longComputation(msg));});}//执行结果主线程执行Randalworkergetmessage:10000000000mainthreadgetmessage:49999999990067860000computetimehow4.95threadselapsed:1transferdata?port.postMessag(value[,transferList])除了value,postMessage该方法还支持传入transferList参数。transferList是一个List,支持的数据类型包括ArrayBuffer和MessagePort对象。transferList中的对象传输完成后,不能在发送该对象的线程中使用。const{Worker,isMainThread,parentPort}=require('worker_threads');//主线程if(isMainThread){constsab=newArrayBuffer(Int32Array.BYTES_PER_ELEMENT*100);constia=newInt32Array(sab);for(leti=0;i{console.log('传输后:',sab);},1000);}}else{console.log("thisisn'tmainthread");}//输出结果thisisthemainthreadbeforetransfer:ArrayBuffer{byteLength:400}thisisn'tmainthreadaftertransfer:ArrayBuffer{byteLength:0}如果ArrayBuffer是按值传输的(并且不存在于transferList中),则传输的是一个副本,如下所示:w.postMessage(sab);//outputresultthisisthemainthreadbeforetransfer:ArrayBuffer{byteLength:400}thisisn'tmainthreadaftertransfer:ArrayBuffer{byteLength:400}线程之间怎么样共享内存?轮到SharedArrayBuffer上场了。如果postMessage中的值为SharedArrayBuffer,则线程可以共享内存,如下例所示:SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT*5);constia=newInt32Array(sab);for(leti=0;i{console.log(ia);});}}else{parentPort.on('message',(msg)=>{constia=newInt32Array(msg,0,1);ia[0]=ia[0]+1;parentPort.postMessage('done');});}//输出结果Int32Array[1,1,2,3,4]Int32Array[2,1,2,3,4]开源库推荐一个封装线程的开源库microjobMicrojob是一个用于Node.js线程的微型包装器,旨在使用匿名函数执行繁重的CPU负载。所以,Microjob将Node.js线程视为临时工作单元:如果你需要生成一个长期存在的线程ead,那么你应该使用默认的API。()=>{leti=0for(i=0;i<1000000;i++){//CPU负载过重...}returni})console.log(res)//1000000}catch(err){console.error(err)}})()参考资料https://medium.com/dailyjs/th...https://nodejs.org/dist/lates...

最新推荐
猜你喜欢