web-dev-qa-db-ja.com

JavaScriptマルチスレッド

JavaScriptでマルチスレッドを実装する(実際のまたは偽の)いくつかの異なる方法の比較に取り組んでいます。私の知る限り、WebワーカーとGoogle Gears WorkerPoolだけが実際のスレッドを提供できます(つまり、実際の並列実行で複数のプロセッサに分散します)。私は次の方法を見つけました:

  • yield()を使用してタスクを切り替える

  • もう1つのスレッドを待機しているスレッドでsetInterval()(または他の非ブロッキング関数)を使用する

  • google Gears WorkerPoolスレッドを使用する(プラグイン付き)

  • html5 Webワーカーを使用する

私は関連する質問を読み、上記の方法のいくつかのバリエーションを見つけましたが、それらの質問のほとんどは古いので、いくつかの新しいアイデアがあるかもしれません。

私は疑問に思っています-JavaScriptで他にどのようにマルチスレッドを実現できますか?他の重要な方法はありますか?

UPDATE:コメントで指摘されているように、私が実際に意味したのは同時実行性でした。

UPDATE 2:Silverlight + JScriptがマルチスレッドをサポートしているという情報を見つけましたが、これを確認できません。

更新3:Googleは廃止されたGears: http://code.google.com/apis/gears/api_workerpool.html

32
Chris Hasiński

Webワーカー 。これはW3C標準(現時点ではワーキングドラフト)であり、プラグインは必要ありません。

この仕様は、Webアプリケーションの作成者がメインページと並行してスクリプトを実行するバックグラウンドワーカーを生成できるようにするAPIを定義しています。

この仕様では、真の同時実行性を実現するために、ワーカーを複数のコアに分散させることについても説明しています(これはブラウザーのJavaScriptエンジンによって見えないように処理されます)。

マルチコアCPUが普及しているため、パフォーマンスを向上させる1つの方法は、計算コストのかかるタスクを複数のワーカー間で分割することです。 [1]の例では、1から10,000,000の数値ごとに実行される計算コストの高いタスクが、10人のサブワーカーにファームアウトされます。

yield()setInterval()は、後で発生するようにスケジュールするだけで、他のものと同時に実行されることはありません。

25
s4y

私は疑問に思っています-JavaScriptで他にどのようにマルチスレッドを実現できますか?他の重要な方法はありますか?

明示的なループや直接の関数呼び出しがないJavaScriptコードにコードを変換することができます。代わりに、コードは、スレッドエンジンによって管理される小さなnits実行に分割されます。私のサンプルコードでは、ループを持つ関数がどのように変換されるかを示していますが、例を単純にするために、関数呼び出しのメカニズムを省略しています。

変換のプロセスは基本的に、分割点でsplittingコードによって機能します。これらの分割ポイントは、関数呼び出しとループです(上記で説明)。例ではオブジェクトとキーを使用しましたが、unitsstackをオブジェクト変数として(つまり、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};
  }
}
4
Keldon Alleyne

Multithread.js は、Webワーカーをラップし、大部分の作業を代行してくれる、JSでの本当に簡単なマルチスレッド化のためのライブラリです。 :)

3
kwh

JavaScriptでのマルチスレッドの直接サポートはありません。ただし、いくつかのアイデアと方法を適用することでこれを実現できます。

次のような方法があります。

var id = window.timeout("javascript code", time);

ここでは、JavaScriptコードが指定された時間の後に呼び出され、使用できます

window.clearTimeout(id);

クリア用。これにより、偽の同時実行を実現できます。

2
user862876

q:他にどのようにJavaScriptで並行性を実現できますか

非同期または「非ブロッキング」タイプのメソッドを使用できます。これは、node.jsシステムに関する大きな話題の1つです。正確にはマルチスレッドではありませんが、高速になる傾向があります。

1
BenG