この記事では、js スレッドのメカニズムとイベントのメカニズムについて詳しく説明します (写真とテキスト)。必要な方は参考にしていただければ幸いです。 。 ヘルプ。
1. プロセスとスレッド
1.プロセスとは、固有のメモリ空間を占有するプログラムの実行を指します。プロセスは Windows タスク マネージャー
(以下を参照) で確認できます。同時に、同じコンピュータ システムで 2 つ以上のプロセスを並列状態にすることができます。これがマルチプロセスです。たとえば、コンピュータでは WeChat、QQ、およびさまざまなブラウザを同時に実行できます。一部のブラウザーは、Firefox や古いバージョンの IE など、単一プロセスで実行されます。また、一部のブラウザーは、chrome や新しいバージョンの IE など、複数のプロセスで実行されます。
2. スレッド
Word など、一部のプロセスは同時に複数のことを実行できます。入力、スペルチェック、印刷などを同時に行うことができます。プロセス内で複数のことを同時に実行したい場合は、プロセス スレッド内で複数の「サブタスク」を同時に実行する必要があります。 スレッドは、CPU の基本スケジューリング単位、プログラム実行の完全なプロセス、およびプロセス内の独立した実行単位を指します。マルチスレッドとは、プロセス内で複数のスレッドを同時に実行することを指します。
ブラウザはマルチスレッドで動作します。たとえば、ブラウザを使用して、曲をダウンロードし、同時にビデオを視聴することができます。さらに、JavaScript 言語の主な機能はシングルスレッドであることを知っておく必要があります。マルチコア CPU の計算能力を活用するために、HTML5 は Web Worker 標準を提案しています。 JavaScript スクリプトは複数のスレッドを作成しますが、子スレッドは完全にメインスレッドの制御の対象となり、DOM を操作してはなりません。したがって、この新しい標準は JavaScript のシングルスレッドの性質を変更しません。
各プロセスは少なくとも 1 つのことを実行する必要があるため、プロセスには少なくとも 1 つのスレッドがあります。もちろん、Word のような複雑なプロセスは複数のスレッドを実行することができ、マルチスレッドの実行方法は複数のプロセスの実行方法と同じであり、複数のスレッドを素早く切り替えます。すべてのスレッドが交互に短時間実行され、同時に実行されているように見えます。もちろん、実際に複数のスレッドを同時に実行するには、マルチコア CPU が必要です。 3. プロセスとスレッド
アプリケーションは特定のプロセスのスレッドで実行する必要があります。プロセス内で少なくとも 1 つの実行スレッド: プロセスの開始後に自動的に作成されるメイン スレッド
プロセス内で複数のスレッドが同時に実行されている場合、
プロセスのメモリ空間は共有されており、各スレッドはこれらの共有メモリを使用できます。
複数のプロセス間でデータを直接共有することはできません
4. シングルスレッドとマルチスレッドの長所と短所は何ですか?
: シーケンシャルプログラミングはシンプルで理解しやすい
マルチスレッドの利点: CPU 使用率を効果的に改善できる
マルチスレッドの欠点:
マルチスレッド作成のオーバーヘッド-threads
スレッド間の切り替えオーバーヘッド
デッドロックと状態同期の問題
2. kernel
1. ブラウザによって異なる場合があります
IE: Trident
最初に例を見て、タイマーが実行されるかどうかを確認してみましょう。 200ms後に実行しますか?
document.getElementById('btn').onclick = function () { var start = Date.now() console.log('启动定时器前...') setTimeout(function () { console.log('定时器执行了', Date.now() - start) }, 200) console.log('启动定时器后...') // 做一个长时间的工作 for (var i = 0; i <p style="text-align: center;"><span class="img-wrap"><img src="https://img.php.cn//upload/image/139/417/140/1539669885863938.png" title="1539669885863938.png" alt="JSのスレッド機構とイベント機構の詳しい紹介(画像とテキスト)"></span><br>実際には、タイマーは 625 ミリ秒が経過するまで実行されません。タイマーは実際のタイミングで実行されることを保証しません。通常は少し遅れるか、長時間遅れる可能性があります (上記の例など)。</p><p><strong>2 タイマー コールバック関数です。別スレッドで実行する? </strong></p><p><strong>タイマーコールバック関数はメインスレッド上で実行されます。具体的な実装方法を以下に紹介します。 </strong></p><p>4. ブラウザ イベント ループ (ポーリング) モデル<strong></strong></p><p>1. JavaScript がシングルスレッドである理由<strong></strong></p># JavaScript 言語の主な特徴の 1 つはシングルスレッドです。つまり、同時に 1 つのことしか実行できません。では、なぜ JavaScript は複数のスレッドを持てないのでしょうか?これにより効率が向上します。 <p><strong>JavaScript の単一スレッドは、その目的に関連しています。ブラウザーのスクリプト言語としての JavaScript の主な目的は、ユーザーと対話して DOM を操作することです。これにより、シングルスレッドのみが可能であることが決まります。そうでない場合は、非常に複雑な同期の問題が発生します。たとえば、JavaScript に同時に 2 つのスレッドがあるとします。1 つのスレッドが特定の DOM ノードにコンテンツを追加し、もう 1 つのスレッドがそのノードを削除するとします。この場合、ブラウザーはどちらのスレッドを使用すればよいでしょうか。 </strong></p>したがって、複雑さを避けるために、JavaScript は誕生以来シングルスレッドであり、これがこの言語の中心的な機能となっており、今後も変更されることはありません。 <p>マルチコア CPU のコンピューティング能力を活用するために、</p>HTML5 は Web Worker 標準を提案しています。これにより、JavaScript スクリプトは複数のスレッドを作成できますが、子スレッドはメインスレッドによって完全に制御されるため、 DOM<p> では操作できません。したがって、この新しい標準は JavaScript のシングルスレッドの性質を変更しません。 <br><strong></strong>2.イベント ループ</p><p><strong>JavaScript のすべてのタスクは 2 つのタイプに分類できます。1 つは同期タスク、もう 1 つは非同期タスク (さまざまなブラウザ イベントなど) 、タイマー、Ajax など)。 </strong> 同期タスクとは、メイン スレッドで実行するためにキューに入れられたタスクを指します。次のタスクは、前のタスクが実行された後にのみ実行できます。非同期タスクは、メイン スレッドには入らないが「タスク キュー」に入るタスクを指します。タスク キュー)。キュー)、「タスク キュー」が非同期タスクを実行できることをメイン スレッドに通知した場合にのみ、タスクは実行のためにメイン スレッドに入ります。 </p><p>具体的には、非同期実行の動作仕組みは以下のとおりです。 (同期実行についても同様です。非同期タスクがなければ非同期実行とみなすことができるためです。) <strong></strong>(1) すべての同期タスクはメインスレッドで実行され、実行コンテキスト スタックを形成します。 </p><p>(2) メインスレッドの他に「タスクキュー」もあります。非同期タスクに実行結果がある限り、イベントは「タスク キュー」に配置されます。 </p><p>(3) 「実行スタック」内のすべての同期タスクが完了すると、システムは「タスク キュー」を読み取り、その中にどのようなイベントがあるかを確認します。これらの対応する非同期タスクは待機状態を終了し、実行スタックに入り、実行を開始します。 </p><p>(4) メイン スレッドは上記の 3 番目の手順を繰り返します。</p><p></p>メイン スレッドは「タスク キュー」からイベントを読み取ります。このプロセスは周期的であるため、プロセス全体が動作します。このメカニズムはイベント ループとも呼ばれます。 <p></p><p><strong></strong></p>#次の例はイベント ループをよく示しています: <p style="max-width:90%"></p><pre class="brush:php;toolbar:false"> setTimeout(function () { console.log('timeout 2222') alert('22222222') }, 2000) setTimeout(function () { console.log('timeout 1111') alert('1111111') }, 1000) setTimeout(function () { console.log('timeout() 00000') }, 0)//当指定的值小于 4 毫秒,则增加到 4ms(4ms 是 HTML5 标准指定的,对于 2010 年及之前的浏览器则是 10ms) function fn() { console.log('fn()') } fn() console.log('alert()之前') alert('------') //暂停当前主线程的执行, 同时暂停计时, 点击确定后, 恢复程序执行和计时 console.log('alert()之后')
注意する必要がある点が 2 つあります。
タイマー ゼロ遅延 (setTimeout(func, 0)) は、コールバック関数が次のことを意味するわけではありません。すぐに実行されました。コールバック関数は少なくとも 4ms まで実行されません。それは、メインスレッドが現在アイドル状態であるかどうか、および「タスクキュー」内でメインスレッドの前で待機しているタスクによって異なります。概要: 非同期タスク (さまざまなブラウザ イベント、タイマー、Ajax など) は、まず (タイマーが指定されたパラメーターに達したとき) 「タスク キュー」に追加されます。 Stackスタック(JavaScriptメインスレッド)が空の場合、Queueキュー(タスクキュー)の最初のタスク(キューヘッド)が読み込まれ、最後に
が実行されます。5. H5 Web ワーカー (マルチスレッド)
1. Web ワーカーの役割
, JavaScript はシングルスレッドです。ページが複雑な操作を含む js ファイルを読み込むと、ユーザー インターフェイスが一時的に「フリーズ」し、他の操作が実行できなくなることがあります。たとえば、次の例:<input> <button>计算</button> <script> // 1 1 2 3 5 8 f(n) = f(n-1) + f(n-2) function fibonacci(n) { return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2) //递归调用 } var input = document.getElementById('number') document.getElementById('btn').onclick = function () { var number = input.value var result = fibonacci(number) alert(result) } </script>
很显然遇到这种页面堵塞情况,很影响用户体验的,有没有啥办法可以改进这种情形?----Web Worker就应运而生了!
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。其原理图如下:
主线程
首先主线程采用new命令,调用Worker()构造函数,新建一个 Worker 线程
var worker = new Worker('work.js');
然后主线程调用worker.postMessage()方法,向 Worker 发消息。
接着,主线程通过worker.onmessage指定监听函数,接收子线程发回来的消息。
var input = document.getElementById('number') document.getElementById('btn').onclick = function () { var number = input.value //创建一个Worker对象 var worker = new Worker('worker.js') // 绑定接收消息的监听 worker.onmessage = function (event) { console.log('主线程接收分线程返回的数据: '+event.data) alert(event.data) } // 向分线程发送消息 worker.postMessage(number) console.log('主线程向分线程发送数据: '+number) } console.log(this) // window
Worker 线程
Worker 线程内部需要有一个监听函数,监听message事件。
通过 postMessage(data) 方法来向主线程发送数据。
//worker.js文件 function fibonacci(n) { return n<p>这样当分线程在计算时,用户界面还可以操作,而且更早拿到计算后数据,响应速度更快了。</p><p style="text-align: center;"><img src="https://img.php.cn//upload/image/673/101/817/1539670027106347.gif" title="1539670027106347.gif" alt="JSのスレッド機構とイベント機構の詳しい紹介(画像とテキスト)"><span class="img-wrap"></span></p><p><strong>3. Web Workers的缺点</strong></p>
不能跨域加载JS
worker内代码不能访问DOM(更新UI)
不是每个浏览器都支持这个新特性(本文例子只能在Firefox浏览器上运行,chrome不支持)
以上がJSのスレッド機構とイベント機構の詳しい紹介(画像とテキスト)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。