Многопоточность JavaScript
Я работаю над сравнением для нескольких разных методов реализации (реального или поддельного) многопоточности в JavaScript. Насколько я знаю, только веб-работники и Google Gears WorkerPool могут дать вам реальные потоки (то есть, распределить по нескольким процессорам с реальным параллельным исполнением). Я нашел следующие методы:
-
переключаться между задачами с помощью yield()
-
использовать setInterval()
(или другую неблокирующую функцию) с потоками, ожидающими одного для другого
-
использовать потоки Google Gears WorkerPool (с плагином)
-
использовать html5 веб-работников
Я прочитал связанные вопросы и нашел несколько вариантов вышеупомянутых методов, но большинство из этих вопросов старые, поэтому может появиться несколько новых идей.
Мне интересно - как еще вы можете добиться многопоточности в JavaScript? Любые другие важные методы?
ОБНОВЛЕНИЕ: Как указано в комментариях, я действительно имел в виду concurrency.
ОБНОВЛЕНИЕ 2: Я нашел информацию о том, что Silverlight + JScript поддерживает многопоточность, но я не могу проверить это.
ОБНОВЛЕНИЕ 3: Google устарел Gears: http://code.google.com/apis/gears/api_workerpool.html
Ответы
Ответ 1
Веб-работники. Theyre стандарт W3C (ну, рабочий проект на данный момент) именно для этого и не требует плагинов:
Эта спецификация определяет API, который позволяет авторам веб-приложений порождать фоновых работников, запускающих скрипты параллельно их главной странице.
В спецификации также обсуждается распространение сотрудников по нескольким ядрам, для true concurrency (это обрабатывается незаметно движком JavaScript браузеров):
При одновременном использовании многоядерных процессоров одним из способов повышения производительности является разделение вычислительно дорогостоящих задач среди нескольких сотрудников. В [одном] примере вычисляемая дорогостоящая задача, которая должна выполняться для каждого номера от 1 до 10 000 000, обрабатывается десятью подработчиками.
yield()
и setInterval()
только планируют, что события произойдут позже, они не запускаются одновременно ни с чем другим.
Ответ 2
Мне интересно - как еще вы можете добиться многопоточности в JavaScript? Любые другие важные методы?
Вы можете преобразовать свой код в код JavaScript, который не имеет явных циклов или прямых вызовов функций, вместо этого код делится на небольшие единицы выполнения, которые управляются механизмом потоковой передачи. В моем примере кода я показываю, как функция с циклами будет преобразована, но я опустил механизм для вызовов функций, просто чтобы простой пример.
Процесс преобразования в основном работает, разбивая код в точках деления. Эти точки деления - это вызовы функций и циклы (как показано выше). В примере я использовал объекты и ключи, но может быть намного проще в JavaScript-браузере браузера, если единицы хранят стек как объектную переменную (т.е. Сохраняют с помощью this.foo = bar
вместо stack["foo"] = bar
).
Например, следующий код:
// Phoney method purely to demonstrate structure
function Foo() {
var i,
sum = 0,
accumulator_list = [],
accumulator_modulus = [],
kMaxAccumulatorCount = 100;
// Calculate accumulations
for(i = 0; i < kMaxAccumulatorCount; ++i) {
current_accumulator = GetNextAccumulator()
accumulator_list[i] = current_accumulator;
sum = sum + current_accumulator;
}
// Calculate accumulator modulus
for(i = 0; i < kMaxAccumulatorCount; ++i) {
current_accumulator = accumulator_list[i];
accumulator_modulus[i] = current_accumulator % kMaxAccumulatorCount;
}
}
... в нечто подобное:
function Foo_A(caller,stack) {
var stack = {};
stack["i"] = undefined;
stack["sum"] = 0;
stack["accumulator_list"] = [];
stack["accumulator_modulus"] = [];
stack["kMaxAccumulatorCount"] = 100;
stack["i"] = 0;
return {caller: caller, stack: stack, next=Foo_B};
}
function Foo_B(caller, stack) {
stack["current_accumulator"] = GetNextAccumulator();
stack["accumulator_list"][stack["i"]] = stack["current_accumulator"];
stack["sum"] = stack["sum"] + stack["current_accumulator"];
// For-loop condition satisfied ?
if(stack["i"] < stack["kMaxAccumulatorCount"]) {
++stack["i"];
return {caller: caller, stack: stack, next:Foo_B};
} else {
// Initialise the next for loop.
stack["i"] = 0;
return {caller: caller, stack: stack, next:Foo_C};
}
}
function Foo_C(caller, stack) {
stack["current_accumulator"] = stack["current_accumulator"][stack["i"]];
stack["accumulator_modulus"][stack["i"]] = stack["current_accumulator"] % stack["kMaxAccumulatorCount"];
// For-loop condition satisfied ?
if(stack["i"] < stack["kMaxAccumulatorCount"]) {
++stack["i"];
return {caller: caller, stack: stack, next:Foo_C};
} else {
// Function has finished so the next will be null. When the thread-engine sees this it simulates the behaviour of a return, pops its virtual stack and returns execution to the caller
return {caller: caller, stack: stack, next:null};
}
}
Ответ 3
Multithread.js - это библиотека для очень простой многопоточности в JS, которая обертывает Web Workers и делает большую часть вашей работы за вас.:)
Ответ 4
Нет прямой поддержки многопоточности в JavaScript. Однако вы можете достичь этого, применив некоторые идеи и методы.
Существуют такие методы, как:
var id = window.timeout("javascript code", time);
здесь код JavaScript вызывается после указанного времени, и мы можем использовать
window.clearTimeout(id);
для очистки.
Благодаря этому мы можем достичь поддельных concurrency.
Ответ 5
q: как еще вы можете достичь concurrency в Javascript
Вы можете использовать методы типа async или 'non-blocking'. Это один из главных жуков в системе node.js.
Это не совсем многопоточное, но оно имеет тенденцию быть быстрее.