JavaScript_javascriptスキルにおけるWebワーカーのマルチスレッドAPIに関する研究

WBOY
リリース: 2016-05-16 16:28:39
オリジナル
1604 人が閲覧しました

HTML5 は Web Worker などの API をサポートしており、Web ページでマルチスレッド コードを安全に実行できるようになります。しかし、実際にはWeb Workerには多くの制限があり、メモリデータを完全に共有することはできず、ステータス通知もメッセージでしか行えないため、本当の意味での「マルチスレッド」とは言えません。

Web Worker のインターフェースは、基本的にサンドボックスが付属しており、サンドボックス内で独立した js ファイルを実行し、postMessage および onMessage を通じてメインスレッドと通信します。

コードをコピーします コードは次のとおりです:

var worker = new Worker("my.js");
var Bundle = {message:'Hello world', id:1};
worker.postMessage(bundle); //postMessage はシリアル化可能なオブジェクトを渡すことができます
worker.onmessage = function(evt){
Console.log(evt.data); //ワーカーから返されたオブジェクトとメインスレッドのオブジェクトを比較します
console.log(bundle); //{メッセージ:'Hello world', id:1}
}

コードをコピーします コードは次のとおりです:

//my.js内
onmessage = function(evt){
var data = evt.data;
データ.id ;
PostMessage(data); //{メッセージ:'Hello world', id:2}
}

得られた結果は、スレッド内で取得したデータのIDが増加していることがわかりますが、それが返された後、メインスレッドのバンドル内のIDは変化していないため、スレッドに渡されたオブジェクトが返されます。実際にはコピーされるため、その場合、スレッドはデータを共有せず、読み取りと書き込みの競合を回避できるため、安全です。スレッドの安全性を確保する代償として、スレッド内のメイン スレッド オブジェクトを操作する機能が制限されます。

このような制限されたマルチスレッド メカニズムは、使用するのが非常に不便です。たとえば、次のようなコードをサポートしているように Worker がサポートできることを期待しています。以下:

コードをコピーします コードは次のとおりです:

var worker = new ThreadWorker(bundle /*shared obj*/);

worker.run(function(bundle){
// ワーカースレッドで sth を実行します...
This.runOnUiThread(function(bundle /*shared obj*/){
// メイン UI スレッドで sth を実行します...
});
//...
});

このコードでは、ワーカーを開始した後、ワーカー内で任意のコードを実行でき、UI スレッドを操作する必要があるとき (DOM の読み取りと書き込みなど)、メイン スレッドに戻って実行できます。 this.runOnUiThread を通じて。

では、このメカニズムを実装するにはどうすればよいでしょうか? 以下のコードを見てください:

コードをコピーします コードは次のとおりです:

function WorkerThread(sharedObj){
This._worker = new Worker("thread.js");
This._completes = {};
This._task_id = 0;
This.sharedObj =sharedObj;

var self = this;
This._worker.onmessage = function(evt){
var ret = evt.data;
If(ret.__UI_TASK__){
// ui タスクで実行
var fn = (new Function("return " ret.__UI_TASK__))();
fn(ret.sharedObj);
}その他{
self.sharedObj = ret.sharedObj;
self._completes[ret.taskId](ret);
}
}
}

WorkerThread.prototype.run = function(タスク、完了){
var _task = {__THREAD_TASK__:task.toString()、sharedObj: this.sharedObj、taskId: this._task_id};
This._completes[this._task_id ] = 完了; This._worker.postMessage(_task);
}

上記のコードは、Thread.js を実行する Web ワーカーを作成し、共有オブジェクト SharedObj を保存し、thread.js によって返されたメッセージを処理する ThreadWorker オブジェクトを定義します。

thread.js から UI_TASK メッセージが返された場合は、メッセージによって渡された関数を実行します。それ以外の場合は、run の完全なコールバックを実行します。thread.js の記述方法を見てみましょう。

コードをコピーします コードは次のとおりです:

onmessage = function(evt){
var data = evt.data;

if(データ && データ.__THREAD_TASK__){
var task = data.__THREAD_TASK__;
試してみましょう{
var fn = (new Function("return " task))();

var ctx = {
threadSignal: true、
スリープ: 関数(間隔){
ctx.threadSignal = false;
setTimeout(_run, interval);
},
runOnUiThread: function(タスク){
PostMessage({__UI_TASK__:task.toString(),sharedObj:data.sharedObj});
}
}

関数 _run(){
ctx.threadSignal = true;
var ret = fn.call(ctx, data.sharedObj);
PostMessage({error:null, returnValue:ret, __THREAD_TASK__:task,sharedObj:data.sharedObj, taskId:data.taskId});
}

_run(0);

}キャッチ(例){
PostMessage({error:ex.toString(), returnValue:null,sharedObj: data.sharedObj});
}
}
}

ご覧のとおり、thread.js は ui スレッドからメッセージを受け取ります。その中で最も重要なものは THREAD_TASK です。これは、関数以降、ui スレッドによって渡され、ワー​​カー スレッドによって実行される必要がある「タスク」です。渡されるのは文字列です。ワーカー スレッドは文字列を関数に解析して、メイン スレッドによって送信されたタスクを実行します (実行完了後、共有オブジェクトsharedObj がタスクに渡されることに注意してください)。返された結果は、メッセージを通じて ui スレッドに渡されます。詳しく見てみましょう。戻り値 returnValue に加えて、共有オブジェクトsharedObjも返されます。これは、ワーカー スレッドと ui スレッドがオブジェクトを共有していないため、両方のオブジェクトを人工的に同期させます。割り当て (このスレッドは安全ですか? ? なぜですか? )

この実装後、この ThreadWorker は次の 2 つの方法で使用できることがわかります。

コードをコピー コードは次のとおりです:

var t1 = new WorkerThread({i: 100} /*共有オブジェクト*/);

setInterval(function(){
            t1.run(function(sharedObj){
                    戻りsharedObj.i ;
                }、
                関数(r){
                    console.log("t1>" r.returnValue ":" r.error);
                }
            );
        }, 500);
var t2 = 新しい WorkerThread({i: 50});

t2.run(function(sharedObj){
            while(this.threadSignal){
                共有オブジェクト;

this.runOnUiThread(function(sharedObj){
                    W("body ul").appendChild("

  • "sharedObj.i "
  • ");
                    });

    this.sleep(500);
                }
                戻りsharedObj.i;
            }、関数(r){
                console.log("t2>" r.returnValue ":" r.error);
            });

    このような使用方法は、形式と説明の両方から、良好な構造、電気活性、および耐久性を備えていると考えられます。

    よろしくお願いします。Web Worker の使用法探索については、ここにアクセスします。興味のある同学は次のこの項目を参照してください: https://github.com/akira-cn/WorkerThread.js (Worker が必要なサービスの調査のため) 、私は特に、非常に厳格な http サービスの js である 1 つの山に httpd.js を配置しました。ノードから直接接続できます)。


    ソース:php.cn
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
    最新の問題
    人気のチュートリアル
    詳細>
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート
    私たちについて 免責事項 Sitemap
    PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!