Как создавать потоки в nodejs


91

Есть ли способ создать потоки для одновременного запуска нескольких методов?

Таким образом, если какой-либо метод выйдет из строя, все остальные потоки должны быть убиты.

Ответы:


94

Каждый процесс node.js спроектирован как однопоточный. Следовательно, чтобы получить несколько потоков, у вас должно быть несколько процессов (как указывали некоторые другие плакаты, есть также библиотеки, на которые вы можете ссылаться, которые дадут вам возможность работать с потоками в Node, но без этих библиотек такой возможности нет. . См. Ответ Шона Винсента со ссылкой на https://github.com/audreyt/node-webworker-threads )

Вы можете запускать дочерние процессы из основного процесса, как показано здесь, в документации node.js: http://nodejs.org/api/child_process.html . Примеры на этой странице довольно хороши и довольно просты.

Затем ваш родительский процесс может следить за событием закрытия в любом запущенном им процессе, а затем может принудительно закрыть другие процессы, которые вы начали, для достижения типа стратегии «один сбой - все стопы», о которой вы говорите.

См. Также: Node.js на многоядерных машинах.


процессы могут работать параллельно и последовательно?
user87267867 04

2
Дочерние процессы не зависят от родительского процесса. У них есть собственное пространство памяти, PID и время выполнения. Не уверен, что вы имеете в виду под последовательным, но да, они будут работать параллельно и отдельно планироваться ОС для выполнения.
Брайан

как вызвать пользовательские функции как дочерний процесс?
user87267867 04

Как я могу создать дочерний процесс для вызова функции abc () {}
user87267867

2
Ха, не знал об этой библиотеке, но похоже, что, согласно комментарию Алекса Миллса, вы можете выполнить некоторую работу с потоками в Node. При этом следующий вопрос: должны ли вы. . . Node был разработан с нуля, чтобы освободить программистов от сложности, которая связана с потоками, но дает аналогичную производительность для блокировки ввода-вывода. Я отредактирую свой ответ, чтобы учесть тот факт, что это возможно с использованием указанной библиотеки.
Брайан

34

Также существует как минимум одна библиотека для выполнения нативных потоков из Node.js: node-webworker-threads.

https://github.com/audreyt/node-webworker-threads

Это в основном реализует API браузера Web Worker для node.js.


3
это должно быть правильно. ответ, предполагающий, что узел может порождать только процессы, но не потоки, неверен.
Александр Миллс

20

В Node 10.5 теперь есть поддержка многопоточности , но она экспериментальная . Надеюсь, это скоро станет стабильным.

Оформить заказ на следующие ресурсы:


Обновление :

Начиная с Node v11.7.0 , вам не нужно использовать --experimental-workerфлаг.

Примечания к выпуску: https://nodejs.org/en/blog/release/v11.7.0/


9

Вы можете получить многопоточность с помощью Napa.js.

https://github.com/Microsoft/napajs

"Napa.js - это многопоточная среда выполнения JavaScript, построенная на V8, которая изначально была разработана для разработки высоко-итеративных служб с бескомпромиссной производительностью в Bing. По мере ее развития мы считаем полезным дополнять Node.js в задачах, связанных с процессором. , с возможностью выполнения JavaScript в нескольких изоляторах V8 и обмена данными между ними. Napa.js представлен как модуль Node.js, хотя он также может быть встроен в хост-процесс без зависимости от Node.js. "



3

Я нуждался в реальную многопоточности в Node.js и что работало для меня был нить пакетом. Он порождает другой процесс, имеющий собственный цикл сообщений Node.js, поэтому они не блокируют друг друга. Установка проста, а документация поможет вам быстро приступить к работе. Ваша основная программа и рабочие могут взаимодействовать обоими способами, и рабочие «потоки» могут быть убиты при необходимости.

Поскольку многопоточность и Node.js - сложная и широко обсуждаемая тема, было довольно сложно найти пакет, который бы отвечал моим конкретным требованиям. Для записи это не сработало для меня :

  • tiny-worker разрешал порождение воркеров, но они, казалось, использовали один и тот же цикл сообщений (но, возможно, я сделал что-то не так - у потоков было больше документации, дающей мне уверенность, что они действительно использовали несколько процессов, поэтому я продолжал, пока он не работал)
  • webworker-thread не позволял использовать requireмодули в воркерах, которые мне нужны

И для тех, кто спрашивает, зачем мне нужна настоящая многопоточность: для приложения, использующего Raspberry Pi и прерывания. Один поток обрабатывает эти прерывания, а другой заботится о хранении данных (и многого другого).


1
Я ценю отличную мысль, вложенную в этот ответ!
MLissCetrus

3

Nodejs 10.5.0 релиз объявил многопоточности в Node.js . Эта функция все еще экспериментальная. Теперь доступен новый модуль worker_threads .

Вы можете начать использовать рабочие потоки, если используете Node.js v10.5.0 или выше , но это экспериментальный API . По умолчанию он недоступен: вам нужно включить его с помощью  --experimental-worker при вызове Node.js.

Вот пример с включенными ES6 и worker_threads , протестированный на версии 12.3.1

//package.json

  "scripts": {
  "start": "node  --experimental-modules --experimental- worker index.mjs"
  },

Теперь вам нужно импортировать Worker из worker_threads . Примечание. Для поддержки ES6 вам необходимо объявить файлы js с расширением .mjs.

//index.mjs
import { Worker } from 'worker_threads';

const spawnWorker = workerData => {
    return new Promise((resolve, reject) => {
        const worker = new Worker('./workerService.mjs', { workerData });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', code => code !== 0 && reject(new Error(`Worker stopped with 
        exit code ${code}`)));
    })
}

const spawnWorkers = () => {
    for (let t = 1; t <= 5; t++)
        spawnWorker('Hello').then(data => console.log(data));
}

spawnWorkers();

Наконец, мы создаем workerService.mjs

//workerService.mjs
import { workerData, parentPort, threadId } from 'worker_threads';

// You can do any cpu intensive tasks here, in a synchronous way
// without blocking the "main thread"
parentPort.postMessage(`${workerData} from worker ${threadId}`);

Выход:

npm запустить запуск

Hello from worker 4
Hello from worker 3
Hello from worker 1
Hello from worker 2
Hello from worker 5

2
Это ваша статья: blog.logrocket.com/… ?
serv-inc

Нет .. это не ... Я отослал это назад во времени.
priyeshdkr



0

Возможно, вы ищете Promise.race(собственное решение для гонок ввода-вывода, а не потоки)

Предполагая, что вы (или другие лица, ищущие этот вопрос) хотите гонять потоки, чтобы избежать сбоев и избежать затрат на операции ввода-вывода, это простой и естественный способ его выполнения (который не использует потоки). Узел спроектирован как однопоточный (посмотрите цикл событий), поэтому по возможности избегайте использования потоков. Если мое предположение верно, я рекомендую вам использовать Promise.raceс setTimeout(пример в ссылке). С помощью этой стратегии вы будете гонять список обещаний, каждый из которых пытается выполнить некоторую операцию ввода-вывода и отклонять обещание в случае ошибки (в противном случае тайм-аут). Promise.raceЗаявление продолжается после первого разрешения / отказа, который , кажется, что вы хотите. Надеюсь, это кому-то поможет!


2
Это не имеет ничего общего с потоками. Все они работают в одном потоке.
Эван Кэрролл

@EvanCarroll - Спасибо, что предупредили меня, что я недостаточно ясно понимаю. Я предварял его предположением о том, почему кто-то может искать потоки гонок, и отметил, что при этом используются обещания в цикле событий Node. Исходя из другого языка, вполне возможно, что вы хотите выполнить то, что делают потоки, но еще не знакомы с циклом событий или обещаниями. Я хотел отметить, что есть более простые способы добиться этого, если это ваша цель. Я добавил в скобках, что здесь не используются потоки. Дайте мне знать, если это прояснит ситуацию.
smileham

Это также, кажется, отвечает критериям OP: «Если какой-либо метод выйдет из строя между всеми другими потоками, он должен быть убит», поэтому я решил, что это актуально.
smileham

Promise.race выполняет все обещания последовательно, переключаясь с одного на другое в случае асинхронной операции (или await в случае асинхронной функции).
Нагабхушан Бадди

0

Node.js не использует потоки. По словам его изобретателя, это ключевая особенность. На момент изобретения потоки были медленными, проблематичными и трудными. Node.js был создан в результате исследования эффективной одноядерной альтернативы. Большинство энтузиастов Node.js до сих пор цитируют старые доводы, как будто потоки не улучшались за последние 50 лет.

Как вы знаете, Node.js используется для запуска JavaScript. Язык JavaScript также развивался на протяжении многих лет. Теперь у него есть способы использования нескольких ядер - то есть, что делают потоки. Таким образом, с помощью усовершенствований JavaScript вы можете выполнять в своих приложениях многоядерную многозадачность. user158 отмечает, что Node.js немного играет с этим. Я ничего об этом не знаю. Но зачем ждать, пока Node.js одобрит то, что предлагает JavaScript.

Google для многопоточности JavaScript вместо многопоточности Node.js. Вы узнаете о веб-воркерах, обещаниях и многом другом.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.