您好,登錄后才能下訂單哦!
nodejs中怎么創建線程,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
當我們調用new Worker的時候,最后會調用c++的StartThread函數(node_worker.cc)創建一個線程。
CHECK_EQ(uv_thread_create_ex(&w->tid_, &thread_options, [](void* arg) {
// ...
}, static_cast<void*>(w)), 0);
我們看uv_thread_create_ex的邏輯
int uv_thread_create_ex(uv_thread_t* tid,
const uv_thread_options_t* params,
void (*entry)(void *arg),
void *arg) {
// 忽略部分代碼
err = pthread_create(tid, attr, f.out, arg);
return UV__ERR(err);
}
接著我們看一下pthread_create的返回值定義
On success, pthread_create() returns 0; on error, it returns an error
number, and the contents of *thread are undefined.
所以,如果uv_thread_create_ex返回非0,即pthread_create返回非0。表示報錯。我們回頭看一下返回非0時,c++的處理。我們對c++層的CHECK_EQ(uv_thread_create_ex(…), 0)進行宏展開。
#define CHECK_EQ(a, b) CHECK((a) == (b))
#define CHECK(expr) \
do { \
if (UNLIKELY(!(expr))) { \
ERROR_AND_ABORT(expr); \
} \
} while (0)
#define UNLIKELY(expr) expr
通過一些列展開,最后變成
do {
if (!(返回值 == 0)) {
ERROR_AND_ABORT(expr);
}
} while (0)
因為創建線程時返回非0,所以這里是true。我們繼續看ERROR_AND_ABORT
#define ERROR_AND_ABORT(expr) \
do {
static const node::AssertionInfo args = { \
__FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME \
}; \
node::Assert(args); \
} while (0)
拼接錯誤信息,然后執行node::Assert(args);
[[noreturn]] void Assert(const AssertionInfo& info) {
char name[1024];
GetHumanReadableProcessName(&name);
fprintf(stderr,
"%s: %s:%s%s Assertion `%s' failed.\n",
name,
info.file_line,
info.function,
*info.function ? ":" : "",
info.message);
fflush(stderr);
Abort();
}
重點是Abort,
[[noreturn]] void Abort() {
DumpBacktrace(stderr);
fflush(stderr);
ABORT_NO_BACKTRACE();
}
繼續看ABORT_NO_BACKTRACE
#ifdef _WIN32
#define ABORT_NO_BACKTRACE() _exit(134)
#else
#define ABORT_NO_BACKTRACE() abort()
#endif
所以最終調用的是_exit或abort退出或者終止進程。我們討論linux下的情況。我們看abort函數的說明
The abort() function first unblocks the SIGABRT signal, and then
raises that signal for the calling process (as though raise(3) was
called). This results in the abnormal termination of the process
unless the SIGABRT signal is caught and the signal handler does not
return (see longjmp(3)).
If the SIGABRT signal is ignored, or caught by a handler that
returns, the abort() function will still terminate the process. It
does this by restoring the default disposition for SIGABRT and then
raising the signal for a second time.
abort函數會給進程發送SIGABRT信號,我們可以注冊函數處理這個信號,不過我們還是無法阻止進程的退出,因為他執行完我們的處理函數后,會把處理函數注冊為系統的默認的,然后再次發送SIGABRT信號,而默認的行為就是終止進程。我們來個測試。
const { Worker, threadId } = require('worker_threads');
for (let i = 0; i < 1000; i++) {
const worker = new Worker('var a = 1;', { eval: true });
}
我們創建1000個線程。結果
看完上述內容,你們掌握nodejs中怎么創建線程的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。