Nodejs里的代码是多线程的吗, 为什么有的代码重复执行了多次?[失误.. Closed]

Nodejs里的代码是多线程的吗, 为什么有的代码重复执行了多次?[失误… Closed]

一段效率很低的代码… LiveScript… 古怪字符比较多的样子… 然后很奇怪地发现运行过程打印了很多遍… 按照代码的逻辑. 同样的列表只可能打印一次的呀…

global <<< require \prelude-ls
show = console.log

primes = [2 3 5]
n = 5

not-even = (a, b) -> (mod a, b) isnt 0

is-prime = (n) ->
  s = 0
  e = (length primes) - 1
  for i in [s to e]
    m = primes[i]
    if (mod n, m) is 0 then return no
  yes

loop
  n += 2
  if n >= 20000
    show sum primes
    # show primes
    return
  if is-prime n
    primes.push n
    # show n
  show primes[((length primes) - 5) to ]

打印的结果, 我按了 ctrl + c 取到个一个片段… 明显重复了… 这是为什么?

[ 14831, 14843, 14851, 14867, 14869 ]
[ 14843, 14851, 14867, 14869, 14879 ]
[ 14843, 14851, 14867, 14869, 14879 ]
[ 14843, 14851, 14867, 14869, 14879 ]
[ 14843, 14851, 14867, 14869, 14879 ]
[ 14851, 14867, 14869, 14879, 14887 ]
[ 14851, 14867, 14869, 14879, 14887 ]
[ 14867, 14869, 14879, 14887, 14891 ]
[ 14867, 14869, 14879, 14887, 14891 ]
[ 14867, 14869, 14879, 14887, 14891 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]
[ 14869, 14879, 14887, 14891, 14897 ]

发现是我理解错误… 抱歉, 废贴了


4 回复

Node.js 里的代码是多线程的吗?为什么有的代码重复执行了多次?

背景

Node.js 是一种基于 Chrome V8 JavaScript 引擎的 JavaScript 运行环境。默认情况下,Node.js 的主要执行环境是单线程的,这使得它非常适合处理 I/O 密集型任务。然而,有时你可能会遇到某些代码被重复执行的情况,这通常与代码逻辑或运行环境有关。

示例代码

让我们来看一下你提供的代码,并分析为什么会出现重复输出的情况。

const primes = [2, 3, 5];
let n = 5;

const notEven = (a, b) => (a % b) !== 0;

const isPrime = (n) => {
  const s = 0;
  const e = primes.length - 1;
  for (let i = s; i <= e; i++) {
    const m = primes[i];
    if (n % m === 0) return false;
  }
  return true;
};

while (true) {
  n += 2;
  if (n >= 20000) {
    console.log(primes.reduce((a, b) => a + b, 0));
    break;
  }
  if (isPrime(n)) {
    primes.push(n);
  }
  console.log(primes.slice(-5));
}

问题分析

在这段代码中,你使用了一个 while 循环来生成质数并将其添加到数组 primes 中。每次循环结束时,都会打印出当前的前五个质数。

关键点

  • 无限循环:你的代码使用了一个无限循环(while (true)),这会导致代码持续运行直到满足某个条件(如 n >= 20000)。
  • 重复输出:由于你使用 console.log(primes.slice(-5)) 来打印当前的前五个质数,每次循环都会执行这个操作,因此会看到多次重复的输出。

解决方案

如果你希望避免重复输出,可以考虑以下几种方法:

  1. 移除不必要的 console.log:如果你只想在特定条件下打印结果,可以在条件满足时再进行输出。

    if (isPrime(n)) {
      primes.push(n);
      if (n % 10 === 0) { // 每10个质数打印一次
        console.log(primes.slice(-5));
      }
    }
    
  2. 使用异步编程:如果需要更复杂的控制流,可以考虑使用异步函数和 async/await

    async function findPrimes() {
      while (true) {
        n += 2;
        if (n >= 20000) {
          console.log(primes.reduce((a, b) => a + b, 0));
          break;
        }
        if (isPrime(n)) {
          primes.push(n);
          if (n % 10 === 0) { // 每10个质数打印一次
            console.log(primes.slice(-5));
          }
        }
      }
    }
    
    findPrimes();
    

通过这些调整,你可以更好地控制代码的执行流程,避免不必要的重复输出。


看不懂这个所谓的LiveScript是个神马东西,猜一下应该是这段代码的问题:

loop
  n += 2
  if n >= 20000
    show sum primes
    # show primes
    return
  if is-prime n
    primes.push n
    # show n
  show primes[((length primes) - 5) to ]

那个loop貌似是一个循环,但是没有循环退出条件,就像JavaScript中这样的死循环了:

for (;;) {
  // ......
}

不好意思… 是我错了… 代码逻辑是两个相邻的质数中间都会打印一遍… 我的算法太慢要跑很久. 弄错了结果. … 正在发愁怎么把这贴删掉…

说起来在哪儿看到过 V8 会把 JS 程序优化成多线程的. 不知道是不是真的… 我当时没理解就往那儿想了…

Node.js 是单线程的,它使用事件循环(Event Loop)来处理异步操作。因此,在Node.js中代码默认不会同时运行多个线程。如果代码出现重复执行的情况,可能是由于以下几个原因:

  1. 全局变量或共享状态:如果你在一个循环或多个回调函数中修改了一个全局变量,可能会导致重复输出。
  2. 异步代码的误解:如果你在异步函数中误用了回调或者Promise,可能会导致某些代码块被多次调用。

从你提供的代码来看,问题出在show primes[((length primes) - 5) to ]这一行。因为你在每次循环时都会打印当前的primes数组,所以当你找到新的素数并添加到数组中时,这些值会被多次打印出来。

示例修正代码

global << require('prelude-ls');
const show = console.log;

let primes = [2, 3, 5];
let n = 5;

const notEven = (a, b) => (a % b) !== 0;

const isPrime = (n) => {
  let s = 0;
  let e = primes.length - 1;
  for (let i = s; i <= e; i++) {
    let m = primes[i];
    if ((n % m) === 0) return false;
  }
  return true;
};

while (true) {
  n += 2;
  if (n >= 20000) {
    show(primes.reduce((acc, curr) => acc + curr, 0));
    break;
  }
  if (isPrime(n)) {
    primes.push(n);
  }
}

解释

  • 移除重复打印:将show primes[((length primes) - 5) to ]移到循环之外,只在最后打印一次结果。
  • 使用现代JavaScript语法:代码更简洁,并且更容易理解。

这样修改后,primes数组只会被打印一次,而不是在每次循环中都打印。

回到顶部