ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript はマルチスレッド化できますか?

JavaScript はマルチスレッド化できますか?

高洛峰
高洛峰オリジナル
2016-11-26 10:16:57961ブラウズ

JavaScript の setTimeout と setInterval は、呼び出されるとあらかじめ決められた方法で実行されると思われがちなので、


[javascript] のように、他の人の感情を簡単に欺くことができるメソッドです。
setTimeout(function(){alert('Hello!'); } , 0);
setInterval(callbackFunction , 100);
setTimeout(function(){alert('Hello!'); } , 0); ( callbackFunction , 100);

これは何も考えずに言われたものではなく、JavaScript API ドキュメントで 2 番目のパラメーターの意味が、ここで 0 ミリ秒に設定すると、当然すぐに実行されます。同様に、setInterval の callbackFunction メソッドも 100 秒ごとに即時に実行されます。

しかし、JavaScript アプリケーションの開発経験が増え続け、リッチになったある日、次のような奇妙なコードを見つけました。

setTimeout( function(){document.getElementById('inputField') .focus();},

};

div.onclick = function(){

setTimeout( function(){document.getElementById('inputField) ').focus();}, 0);

};



0 ミリ秒後に実行されるのに、なぜ setTimeout を使用するのでしょうか? この時点で、あなたの確固たる信念が揺らぎ始めました。

最後の日まで、誤って悪いコードを書いてしまいました:


[javascript]

setTimeout ( function(){ while(true){} } , 100);

setTimeout( function(){ warning('Hello!'); } , 200 );
setInterval( callbackFunction , 200);

setTimeout( function( ){ while(true){} } , 100);

setTimeout( function(){ warning('Hello!'); } , 200); ( callbackFunction , 200);



コードの最初の行 無限ループに入りますが、すぐに 2 行目と 3 行目が期待したものではなく、警告メッセージが表示されず、からのニュースがないことがわかります。 callbacKFunction!

現時点では、あなたはこの状況を受け入れるのが難しいです。長年確立された認識を変えて新しいアイデアを受け入れるプロセスは苦痛ですが、事実は私たちの目の前にあり、 JavaScript の真実は痛みを理由に止まらない JavaScript のスレッドとタイマー探求の旅を広げましょう

雲を開けて月明かりを見てください www.2cto.com

上記の誤解の主な理由は次のとおりです。 JavaScript エンジンが複数のスレッドを実行しており、JavaScript タイマー コールバックが非同期で実行されていると無意識に信じ込んでいます

実際、JavaScript はほとんどの場合、私たちの目を欺くために目くらましメソッドを使用していることがわかります。

JavaScript エンジンは、ブラウザーがどこにあるかに関係なく、単一のスレッドで実行されます。 JavaScript プログラムを実行するスレッドは常に 1 つだけです。

JavaScript エンジンを単一のスレッドで実行することも理にかなっています。スレッドは、スレッドの同期などの複雑な問題を気にする必要がなく、問題が単純化されます。

それでは、これらのタイマーを処理し、ブラウザのイベントに応答するために、ブラウザ カーネルと連携する方法とは何でしょうか?以下は、ブラウザ カーネルの処理方法に基づいて簡単に説明します。

ブラウザ カーネルの実装では、複数のスレッドが非同期で実行でき、これらのスレッドは、特定の実装の場合、同期を維持します。ブラウザ カーネルには少なくとも 3 つの常駐スレッドがあります: JavaScript エンジン スレッド、インターフェイス レンダリング スレッド、ブラウザ イベント トリガー スレッド。これらに加えて、HTTP リクエスト スレッドなど、実行後に終了するいくつかのスレッドもあります。これらの非同期スレッドは、別の非同期スレッドを生成します。次の図は、シングルスレッド JavaScript エンジンがどのように他のスレッドと対話し、通信するかを示しています。各ブラウザー カーネルの実装の詳細は異なりますが、呼び出し原理は似ています。

JavaScript の setTimeout と setInterval は、他の人の感情を簡単に欺くことができます。なぜなら、呼び出されると、確立された方法で実行されると考えているからです。たとえば、


写真からわかるように、JavaScript は同じように感じていると思います。ブラウザーのエンジンはイベント駆動型です。ここでのイベントは、ブラウザーによって割り当てられたさまざまなタスクとみなすことができます。たとえば、タスクを追加するために setTimeout を呼び出すと、これらのタスクは現在実行されているコード ブロックから発生する可能性があります。また、インターフェイス要素のマウス クリック イベント、スケジュールされたトリガー時刻の到着通知、非同期リクエスト ステータスの変更通知など、ブラウザ カーネルの他のスレッドからも来ます。コードの観点から見ると、タスク エンティティはさまざまなコールバック関数であり、JavaScript エンジンは次のようになります。タスク キュー内のタスクの到着を待っています。単一スレッドの関係により、これらのタスクはキューに入れられ、エンジンによって次々に処理される必要があります

上の図 t1 ~ t2..tn は、異なる時点を表しています。小さな四角はその時点のタスクを表し、時刻 t1 でエンジンが t1 に対応するタスク ブロック コードで実行されているとします。この時点での他のスレッドのステータスを説明します。ブラウザカーネル内:

T1 時間:

GUI レンダリング スレッド:

このスレッドは、ブラウザ インターフェイスの HTML 要素のレンダリングを担当します。このスレッドは、インターフェイスの再描画 (再描画) が必要な場合、または何らかの操作によってリフローが発生した場合に実行されます。ただし、この記事では JavaScript のタイミング メカニズムについて説明します。現時点ではこれが必要です。レンダリング スレッドについて説明します。このスレッドは JavaScript エンジン スレッドと相互に排他的であるため、JavaScript スクリプトはこれらの要素のプロパティを変更してレンダリングすることができるため、これは簡単に理解できます。

JavaScript エンジンがスクリプトを実行している間、ブラウザのレンダリング スレッドは一時停止状態、つまり「フリーズ」状態になります。

そのため、スクリプト内でノードの追加などのインターフェースを更新しても、ノードの削除やノードの外観の変更などの更新はすぐには反映されません。これらの操作はキューに保存され、JavaScript の実行時にレンダリングされます。エンジンはアイドル状態です。

GUI イベント トリガー スレッド:

JavaScript スクリプト t1 期間では、ユーザーが最初にマウス ボタンをクリックすると、そのクリックがブラウザーのイベント トリガーによってキャプチャされます。図からわかるように、JavaScript エンジン スレッドの場合、このイベントは他のスレッドによってタスク キューの最後に非同期的に送信されます。これは、エンジンが t1 でタスクを処理しているためです。クリック イベントは処理を待機しています。

タイミング トリガー スレッド:

ここでのブラウザ モデルのタイミング カウンターは、ブロックされたスレッド内にある場合、JavaScript エンジンによってカウントされることに注意してください。JavaScript エンジンはシングルスレッドであるためです。状態では、時間をカウントすることはできません。タイミングを計ってトリガーするために外部に依存する必要があるため、キュー内のタイミング イベントも非同期イベントです。

写真からわかるように、この t1 期間中は、その後マウス クリック イベントがトリガーされると、以前に設定された setTimeout タイミングも到着します。このとき、JavaScript エンジンの場合、タイミング トリガー スレッドは非同期タイミング イベントを生成し、このイベントがクリック後にキューに入れられます。イベントコールバック、処理待ちです

同様に、まだt1期間内ですが、一定のsetIntervalタイマーも追加されていますので、t1期間中に2回連続でトリガーされます。

期間 t1 が非常に長く、setInterval タイミング間隔よりもはるかに大きい場合、タイミング トリガー スレッドは継続的に非同期タイミング イベントを生成し、それらをタスク キューの最後まで処理されているかどうかに関係なく、t1 以降の最初のスケジュールされたイベントが処理されると、これらの配置内のスケジュールされたイベントは中断されることなく順番に実行されるためです。処理キュー内の JavaScript エンジン 各タスクは同じ方法で処理されますが、処理の順序は異なります。

t1 が経過した後、つまり現在処理されているタスクが返された後、JavaScript エンジンは次のように処理します。タスクキューをチェックすると、現在のキューが空ではないことがわかり、t2 の最後が取り出されます。対応するタスクが実行されます。この観点から、他の場合も同様です。

キューが空でない場合。 、エンジンはタスクが処理されるまでキューの先頭からタスクを取り出します。つまり、エンジンは戻った後、キュー内の他のタスクを実行することはできません

。これで、JavaScript がマルチスレッド化できるかどうかを明確に理解し、JavaScript タイマーの動作メカニズムについても理解できるようになりました。いくつかのケースを分析してみましょう:

ケース 1: setTimeout と setInterval

[javascript]
setTimeout(function(){
) /* コード ブロック... */
setTimeout(arguments.callee,
}, 10);

setInterval(function (){
/* コード ブロック... */
}, 10); ;
setTimeout(function(){
/* コードブロック... */
setTimeout(arguments.callee, 10);
}, 10 );

setInterval(function(){

/* コードブロック... */
}, 10);

2 つのコードは結合すると同じように見えますが、実際には異なります。最初の段落のコールバック関数では、setTimeout はその後新しい setTimeout タイミングを設定します。 JavaScript エンジンが実行されると、前のコールバック処理の完了から次のコールバック処理の開始までの時間間隔が理論上 10ms 以上に設定されます。 setInterval タイミングの後、タイミング トリガー スレッドは 10 秒ごとに非同期タイミング イベントを継続的に生成し、それらをタスク キューの最後に置きます。理論的には、2 つの setInterval コールバック間の実行時間間隔は ケース 2: ajax 非同期リクエストは本当ですか?

多くのクラスメートや友人は混乱しています。JavaScript は単一のスレッドで実行されると言われているため、接続後の XMLHttpRequest は本当に非同期ですか?

実際、リクエストは確かに非同期ですが、このリクエストは新しいものです。ブラウザーによって開かれたスレッド (上の図を参照)、リクエストのステータスが変更されると、コールバックが事前に設定されている場合、非同期スレッドはステータス変更イベントを生成し、JavaScript エンジンの処理キューに入れます。タスクが処理されるとき、JavaScript エンジンは常にシングルです。スレッドはコールバック関数を実行します。具体的には、onreadystatechange で実行されるシングルスレッドによって設定された関数です。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。