Node.js 中的 Multiple setTimeout 执行是单线程还是多线程?
is Multiple setTimeout execution single threaded or mutli threaded in Node.js?
假设我有 3 个 setTimeout,如下所示:
console.log(new Date().toLocaleTimeString());
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 3000);
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 6000);
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 9000);
由于Node是单线程的,每次超时应该一个接一个的执行。因此输出应该如下所示:
9 am 0s (intial)
9 am 3s(+3s)
9 am 9s(+6s)
9 am 18s(+9s)
但我发现的是:
9 am 0s (initial)
9 am 3s(+3s)
9 am 6s(+3s)
9 am 9s(+3s)
所以很明显所有超时都同时开始了。每个超时之间的差异被添加到每个超时之间,在这种情况下是+3s,
在这种情况下,这会使 nodejs 成为多线程吗?我知道并非节点 运行 的所有部分都在同一个线程中,而且很少有人在同一个线程外执行。
有人可以让我更好地理解这一点。或者我的做法不对。
Since Node is single threaded, execution of each timeout should be one after the other.
Node.js 不是单线程的。但默认情况下它会 运行 一个 JavaScript 线程。您可以通过 worker_threads
module 运行 其他人。 (每个工人都有自己的 JavaScript 环境;他们可以交流。)
Hence the output should be as expected as below:
不,不应该。您的代码正在启动三个计时器 一个接一个 。对 setTimeout
的所有三个调用都立即 运行,启动它们的计时器。然后事件循环继续,等待做某事,大约三秒后,它看到第一个计时器回调的时间到了,所以它 运行 进行了回调。然后事件循环继续。大约三秒后(总共六秒),它发现是时候进行第二次回调了,于是就这样做了。循环继续……三秒后,它进行第三次回调。这一切都在一个线程上。
在 Node.js here 中有更多关于事件循环的内容。
Node 的事件循环与浏览器的类似。这是浏览器中的示例,带有一些额外的日志记录:
const start = Date.now();
function elapsedPrefix() {
return ("+" + (Date.now() - start)).padStart(4, " ");
}
function log(...msgs) {
console.log(`${elapsedPrefix()}: ${msgs.join(" ")}`);
}
function now() {
return new Date().toISOString().substring(11, 12);
}
function startTimeout(num, fn, ms) {
log(`Start timer ${num} for ${ms}ms`);
setTimeout(() => {
log(`Timer ${num} firing`);
fn();
}, ms);
}
log(`Starting timers`);
startTimeout(1, () => { log(new Date().toLocaleTimeString()); }, 3000);
startTimeout(2, () => { log(new Date().toLocaleTimeString()); }, 6000);
startTimeout(3, () => { log(new Date().toLocaleTimeString()); }, 9000);
log(`Timers started`);
假设我有 3 个 setTimeout,如下所示:
console.log(new Date().toLocaleTimeString());
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 3000);
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 6000);
setTimeout(() => { console.log(new Date().toLocaleTimeString()); }, 9000);
由于Node是单线程的,每次超时应该一个接一个的执行。因此输出应该如下所示:
9 am 0s (intial)
9 am 3s(+3s)
9 am 9s(+6s)
9 am 18s(+9s)
但我发现的是:
9 am 0s (initial)
9 am 3s(+3s)
9 am 6s(+3s)
9 am 9s(+3s)
所以很明显所有超时都同时开始了。每个超时之间的差异被添加到每个超时之间,在这种情况下是+3s,
在这种情况下,这会使 nodejs 成为多线程吗?我知道并非节点 运行 的所有部分都在同一个线程中,而且很少有人在同一个线程外执行。
有人可以让我更好地理解这一点。或者我的做法不对。
Since Node is single threaded, execution of each timeout should be one after the other.
Node.js 不是单线程的。但默认情况下它会 运行 一个 JavaScript 线程。您可以通过 worker_threads
module 运行 其他人。 (每个工人都有自己的 JavaScript 环境;他们可以交流。)
Hence the output should be as expected as below:
不,不应该。您的代码正在启动三个计时器 一个接一个 。对 setTimeout
的所有三个调用都立即 运行,启动它们的计时器。然后事件循环继续,等待做某事,大约三秒后,它看到第一个计时器回调的时间到了,所以它 运行 进行了回调。然后事件循环继续。大约三秒后(总共六秒),它发现是时候进行第二次回调了,于是就这样做了。循环继续……三秒后,它进行第三次回调。这一切都在一个线程上。
在 Node.js here 中有更多关于事件循环的内容。
Node 的事件循环与浏览器的类似。这是浏览器中的示例,带有一些额外的日志记录:
const start = Date.now();
function elapsedPrefix() {
return ("+" + (Date.now() - start)).padStart(4, " ");
}
function log(...msgs) {
console.log(`${elapsedPrefix()}: ${msgs.join(" ")}`);
}
function now() {
return new Date().toISOString().substring(11, 12);
}
function startTimeout(num, fn, ms) {
log(`Start timer ${num} for ${ms}ms`);
setTimeout(() => {
log(`Timer ${num} firing`);
fn();
}, ms);
}
log(`Starting timers`);
startTimeout(1, () => { log(new Date().toLocaleTimeString()); }, 3000);
startTimeout(2, () => { log(new Date().toLocaleTimeString()); }, 6000);
startTimeout(3, () => { log(new Date().toLocaleTimeString()); }, 9000);
log(`Timers started`);