HTML5는 웹 작업자와 같은 API를 지원하므로 웹 페이지가 안전한 상황에서 멀티 스레드 코드를 실행할 수 있습니다. 그러나 웹 워커는 실제로 메모리 데이터를 공유 할 수없고 메시지를 사용하여 상태를 알리기 위해 메시지를 사용할 수 있기 때문에 실제로 많은 제한을받습니다. 따라서 진정한 의미에서 "멀티 스레딩"이라고도 할 수 없습니다.
웹 워커의 인터페이스는 사용하기에 매우 불편합니다. 기본적으로 샌드 박스에서 독립적 인 JS 파일을 실행하는 샌드 박스와 함께 제공되며 PostMessage 및 OnMessge를 통해 메인 스레드와 통신합니다.
코드 사본은 다음과 같습니다.
var 노동자 = 신규 노동자 ( "my.js");
var 번들 = {메시지 : 'Hello World', id : 1};
Worker.postmessage (번들); // postMessage는 과거에 직렬화 가능한 객체를 전달할 수 있습니다
worker.onmessage = function (evt) {
Console.log (evt.data); // 메인 스레드의 개체와 함께 작업자에 전달 된 객체를 비교
Console.log (번들); // {메시지 : 'Hello World', id : 1}
}
코드 사본은 다음과 같습니다.
// my.js에서
onmessage = function (evt) {
var data = evt.data;
data.id ++;
사후 관리 (데이터); // {메시지 : 'Hello World', id : 2}
}
결과는 스레드에서 얻은 데이터의 ID가 증가했음을 알 수 있지만, 다시 전달 된 후 기본 스레드 묶음의 ID는 변경되지 않습니다. 따라서 스레드에 전달 된 물체가 실제로 복사됩니다. 이런 식으로 스레드는 데이터를 공유하지 않고 읽기 및 쓰기 충돌을 피하기 때문에 안전합니다. 스레드 안전을 보장하는 비용은 스레드에서 기본 스레드 객체를 작동하는 기능을 제한하는 것입니다.
이러한 제한된 멀티 스레딩 메커니즘은 사용하기에 불편합니다. 물론, 우리는 노동자가 코드가 다중 스레딩을 동시에 작동시키는 것처럼 보일 수있는 능력을 지원할 수 있기를 바랍니다. 예를 들어, 다음과 같은 것처럼 보이는 지원 코드.
코드 사본은 다음과 같습니다.
var worker = 새로운 스레드 워크러 (Bundle /*공유 OBJ* /);
worker.run (함수 (번들) {
// 작업자 스레드에서 STH를 수행 ...
this.runonUithread (함수 (bundle /*shared obj* /) {
// Main UI 스레드에서 STH를 수행합니다 ...
});
// ...
});
이 코드에서는 작업자를 시작한 후 작업자에서 모든 코드를 실행하도록 할 수 있으며 UI 스레드 (예 : DOM 읽기 및 쓰기 등)를 작동해야 할 때 기본 스레드로 돌아가서 this.runonuithread를 통해 실행할 수 있습니다.
그렇다면이 메커니즘을 구현하는 방법은 무엇입니까? 다음 코드를보십시오.
코드 사본은 다음과 같습니다.
기능 Workerthread (sharedobj) {
this._worker = new Worker ( "Thread.js");
this._completes = {};
this._task_id = 0;
this.sharedobj = sharedobj;
var self = 이것;
this._worker.onmessage = function (evt) {
var ret = evt.data;
if (ret .__ ui_task __) {
// UI 작업에서 실행됩니다
var fn = (새 함수 ( "return"+ret .__ ui_task __)) ();
fn (ret.sharedobj);
}또 다른{
self.sharedobj = ret.sharedobj;
self._completes [ret.taskid] (ret);
}
}
}
workerthread.prototype.run = 함수 (작업, 완료) {
var _task = {__thread_task __ : task.tostring (), sharedobj : this.sharedobj, taskid : this._task_id};
this._completes [this._task_id ++] = 완료;
this._worker.postmessage (_task);
}
위의 코드는 Threadworker 객체를 정의합니다. 이 객체는 thread.js를 실행하는 웹 워커를 생성하고 공유 객체 sharedobj를 저장하고 Thread.js가 다시 보낸 메시지를 처리합니다.
ui_task 메시지가 thread.js에서 다시 전송되면이 메시지가 전달한 함수를 실행하십시오. 그렇지 않으면, run의 전체 콜백을 실행하고 Thread.js가 어떻게 작성되는지 보자.
코드 사본은 다음과 같습니다.
onmessage = function (evt) {
var data = evt.data;
if (data && data .__ Thread_task __) {
var task = data .__ Thread_task__;
노력하다{
var fn = (새 함수 ( "return"+task)) ();
var ctx = {
ThreadSignal : True,
수면 : 기능 (간격) {
ctx.threadsignal = false;
settimeout (_run, interval);
},
runonuithread : function (task) {
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);
} catch (ex) {
postMessage ({error : ex.tostring (), returnValue : null, sharedobj : data.sharedobj});
}
}
}
Thread.js는 UI 스레드로부터 메시지를 수신한다는 것을 알 수 있습니다. 가장 중요한 것은 Thread_task이며, 이는 Worker 스레드에서 실행 해야하는 UI 스레드가 통과 한 "작업"입니다. 함수는 직렬화 할 수 없으므로 문자열이 전달됩니다. 작업자 스레드는 주 스레드가 제출 한 작업을 실행하기 위해 문자열을 함수로 구문 분석합니다 (공유 객체 sharedobj가 작업에 전달됨). 실행이 완료되면 반환 결과가 메시지를 통해 UI 스레드로 전달됩니다. 반환 값 returnValue 외에도 공유 객체 SharedObj를 자세히 살펴 보겠습니다. 다시 전달할 때, 작업자 스레드와 UI 스레드가 객체를 공유하지 않기 때문에, 우리는 할당을 통해 양쪽의 객체를 인위적으로 동기화합니다 (이 스레드가 안전합니까? 왜?)
전체 프로세스가 복잡하지 않다는 것을 알 수 있습니다. 이 구현 후이 스레드 워크는 다음 두 가지 용도를 가질 수 있습니다.
코드 사본은 다음과 같습니다.
var t1 = new Workerthread ({i : 100} /*공유 obj* /);
setInterval (function () {
t1.run (function (sharedobj) {
반환 sharedobj.i ++;
},
함수 (r) {
Console.log ( "T1>" + R.ReTurnValue + ":" + r.error);
}
);
}, 500);
var t2 = new Workerthread ({i : 50});
t2.run (function (sharedobj) {
while (this.threadsignal) {
sharedobj.i ++;
this.runonuithread (function (sharedobj) {
W ( "Body Ul"). AppendChild ( "<li>"+sharedobj.i+"</li>");
});
this.sleep (500);
}
반환 sharedobj.i;
}, function (r) {
Console.log ( "T2>" + R.ReTurnValue + ":" + r.error);
});
이 사용법은 코드에 양호한 구조, 유연성 및 유지 보수성을 형태와 의미 론적 용어로 제공합니다.
좋아요, 웹 워커의 사용에 대한 토론의 전부입니다. 관심있는 학생들은이 프로젝트를 살펴볼 수 있습니다 : https://github.com/akira-cn/workerthread.js (작업자가 서버 테스트를 사용해야하므로 프로젝트에 CopyCat httpd.js를 특히 간단한 HTTP 서비스 JS로 직접 실행할 수 있습니다).