成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Node.js知識 — 如何實現線程睡眠?

開發 前端
使用 JavaScript/Node.js 的開發者如果遇到需要實現延遲的任務,可能會有疑問🤔️ 為什么這里沒有類似 Java 中 Thread.sleep() 這樣的方式來實現線程睡眠,本文講解如何在 Node.js 中實現一個 sleep() 函數。

[[386225]]

本文轉載自微信公眾號「Nodejs技術棧」,作者五月君。轉載本文請聯系Nodejs技術棧公眾號。

Node.js 小知識 記錄一些工作中或 “Nodejs技術棧” 交流群中大家遇到的一些問題,有時一個小小的問題背后也能延伸出很多新的知識點,解決問題和總結的過程本身也是一個成長的過程,在這里與大家共同分享成長。

使用 JavaScript/Node.js 的開發者如果遇到需要實現延遲的任務,可能會有疑問🤔️ 為什么這里沒有類似 Java 中 Thread.sleep() 這樣的方式來實現線程睡眠,本文講解如何在 Node.js 中實現一個 sleep() 函數。

一:糟糕的 “循環空轉”

下面這段代碼是糟糕的,Node.js 是以單進程、單線程的方式啟動,所有的業務代碼都工作在主線程,這樣會造成 CPU 持續占用,主線程阻塞對 CPU 資源也是一種浪費,與真正的線程睡眠相差甚遠。

  1. const start = new Date(); 
  2. while (new Date() - start < 2000) {} 

 

運行之后如上圖所示,CPU 暴漲,同時也會破壞事件循環調度,導致其它任務無法執行。

二:定時器 + Promise 實現 sleep

通過定時器延遲執行函數 setTimeout + Promise 的鏈式依賴實現,本質是創建一個新的 Promise 對象,待定時器延遲時間到了執行 resolve 函數這時 then 才會執行,這里 Node.js 執行線程是沒有進行睡眠的,事件循環和 V8 等都是正常運行的。但這也是目前通用的一種解決方案,因為你不能讓主線程阻塞,否則程序就無法繼續工作了。

  1. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); 

在 Node.js 中還可以利用 util 模塊提供的 promisify 方法實現,一種快捷方式。

  1. const { promisify } = require('util'); 
  2. const sleep = promisify(setTimeout); 

因為是基于定時器與 Promise 所以也自然是異步的方式了,使用時也要注意,如下所示:

  1. // async await 的方式 
  2. async function test() { 
  3.   console.log(1); 
  4.   await sleep(3000); 
  5.   console.log(2); 
  6.  
  7. // Promise 的鏈式調用方式 
  8. async function test() { 
  9.   console.log(1); 
  10.   sleep(3000).then(() => { 
  11.     console.log(2); 
  12.   }); 

三:零 CPU 開銷真正的事件循環阻止 sleep 實現

ECMA262 草案提供了 Atomics.wait API 來實現線程睡眠,它會真正的阻塞事件循環,阻塞線程直到超時。

該方法 Atomics.wait(Int32Array, index, value[, timeout]) 會驗證給定的 Int32Array 數組位置中是否仍包含其值,在休眠狀態下會等待喚醒或直到超時,返回一個字符串表示超時還是被喚醒。

同樣的因為我們的業務是工作在主線程,避免在主線程中使用,在 Node.js 的工作線程中可以根據實際需要使用。

  1. /** 
  2.  * 真正的阻塞事件循環,阻塞線程直到超時,不要在主線程上使用  
  3.  * @param {Number} ms delay 
  4.  * @returns {String} ok|not-equal|timed-out 
  5.  */ 
  6. function sleep(ms) { 
  7.   const valid = ms > 0 && ms < Infinity; 
  8.   if (valid === false) { 
  9.     if (typeof ms !== 'number' && typeof ms !== 'bigint') { 
  10.       throw TypeError('ms must be a number'); 
  11.     } 
  12.     throw RangeError('ms must be a number that is greater than 0 but less than Infinity'); 
  13.   } 
  14.  
  15.   return Atomics.wait(int32, 0, 0, Number(ms)) 
  16.  
  17. sleep(3000) 

由于本節我們僅是在講解 sleep 的實現,所以關于 Atomics.wait 方法睡眠之后如何被其它線程喚醒也不再此處講了,之后我會寫一講 Node.js 中的工作線程相關文章,到時會再次介紹。

四:基于 N-API 擴展使用 C 語言實現 sleep

通過 Addon 的方式使用 N-API 編寫 C/C++ 插件,借助其提供的系統 sleep() 函數實現。

  1. // sleep.c 
  2. #include <assert.h> 
  3. #include <unistd.h> 
  4. #include <node_api.h> 
  5.  
  6. napi_value sleepFn(napi_env env, napi_callback_info info) { 
  7.   napi_status status; 
  8.   size_t argc = 1; 
  9.   napi_value argv[1]; 
  10.  
  11.   status = napi_get_cb_info(env, info, &argc, argv, NULLNULL); 
  12.   assert(status == napi_ok); 
  13.   if (argc < 1) { 
  14.     napi_throw_type_error(env, NULL"ms is required"); 
  15.     return NULL
  16.   } 
  17.  
  18.   napi_valuetype valueType; 
  19.   napi_typeof(env, argv[0], &valueType); 
  20.   if (valueType != napi_number) { 
  21.     napi_throw_type_error(env, NULL"ms must be a number"); 
  22.     return NULL
  23.   } 
  24.  
  25.   int64_t s; 
  26.   napi_get_value_int64(env, argv[0], &s); 
  27.   sleep(s); 
  28.   return NULL
  29.  
  30. napi_value init(napi_env env, napi_value exports) { 
  31.   napi_status status; 
  32.   napi_property_descriptor descriptor = { 
  33.     "sleep"
  34.     0, 
  35.     sleepFn, 
  36.     0, 
  37.     0, 
  38.     0, 
  39.     napi_default, 
  40.     0 
  41.   }; 
  42.   status = napi_define_properties(env, exports, 1, &descriptor); 
  43.   assert(status == napi_ok); 
  44.   return exports; 
  45.  
  46. NAPI_MODULE(sleep, init); 

經過一系列編譯之后,引入 .node 文件直接使用。

  1. // app.js 
  2. const { sleep } = require('./build/Release/sleep.node'); 
  3. sleep(3); 

五:easy-sleep 模塊

這是筆者寫的一個小模塊 https://github.com/qufei1993/easy-sleep,其實也是對以上幾種方法的整合,包含了 C 插件的編寫,使用如下:

  1. // Install 
  2. npm install easy-sleep -S 
  3.  
  4. // Async sleep 
  5. const { sleep } = require('easy-sleep'); 
  6. await sleep(3000); 
  7.  
  8. // Thread sleep 
  9. const { Thread } = require('easy-sleep'); 
  10. Thread.sleep(); 

 

總結

由于 JavaScript 是單線程的語言,通常我們都是工作在主線程,如果真的讓線程睡眠了,事件循環也會被阻塞,后續的程序就無法正常工作了,大多數情況,我們也是簡單的對 setTimeout 函數做一些封裝實現延遲功能。在瀏覽器/Node.js 的工作線程下可以根據實際需要決定是否需要工作線程睡眠。

 

責任編輯:武曉燕 來源: Nodejs技術棧
相關推薦

2011-09-09 14:23:13

Node.js

2019-03-29 16:40:02

Node.js多線程前端

2021-05-21 09:36:42

開發技能代碼

2013-11-01 09:34:56

Node.js技術

2015-03-10 10:59:18

Node.js開發指南基礎介紹

2021-01-04 08:09:58

Node.js磁盤接口

2021-05-11 07:45:00

HTTPNode.jsCookie

2022-06-23 06:34:56

Node.js子線程

2021-07-16 04:56:03

NodejsAddon

2011-09-08 13:46:14

node.js

2011-11-01 10:30:36

Node.js

2011-09-02 14:47:48

Node

2011-11-10 08:55:00

Node.js

2012-10-24 14:56:30

IBMdw

2021-05-27 09:00:00

Node.js開發線程

2022-09-04 15:54:10

Node.jsAPI技巧

2021-07-30 11:20:53

JavaScriptNode.jsWeb Develop

2022-08-22 07:26:32

Node.js微服務架構

2022-01-29 22:27:31

內核子線程應用

2021-04-20 12:39:52

Node.js多線程多進程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 操操日 | 日韩欧美三区 | 欧美成人激情 | 亚洲一区二区视频在线观看 | a国产视频 | 亚洲一区二区网站 | 91九色婷婷 | 欧美日韩国产在线 | 国产精品精品视频一区二区三区 | 欧美 日韩 亚洲91麻豆精品 | 国内在线视频 | 欧美综合久久 | 免费激情| 亚洲国产中文字幕 | 成人在线播放网站 | 在线毛片网 | 国产二区在线播放 | 国产精品黄色 | 免费人成在线观看网站 | 在线看一区二区三区 | 欧美中文 | 久久精品色视频 | 欧美日韩久久精品 | 欧美日韩在线一区二区 | 亚洲精品电影在线观看 | 日韩久久网| 亚洲va国产日韩欧美精品色婷婷 | 男女激情网站免费 | 欧美一区二区三区视频 | 夜夜爽99久久国产综合精品女不卡 | www.国产精品 | 欧美一级做性受免费大片免费 | 国产精品视频免费看 | 亚洲v区 | 国产伦一区二区三区四区 | 久久国产视频网站 | 久久久www成人免费精品张筱雨 | 国产精品久久久久久久久久久久久 | 国产精品久久一区 | 亚洲精品中文字幕在线观看 | 黑人巨大精品欧美一区二区免费 |