重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
nodejs中怎么创建线程,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计、网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的永济网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
当我们调用new Worker的时候,最后会调用c++的StartThread函数(node_worker.cc)创建一个线程。
CHECK_EQ(uv_thread_create_ex(&w->tid_, &thread_options, [](void* arg) {
// ...
}, static_cast(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中怎么创建线程的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!