亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

JavaScript中的Web worker多線程API研究

2024-05-06 16:11:33
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了JavaScript中的Web worker多線程API研究,Web worker是HTML5的API,允許網頁在安全的情況下執行多線程代碼,需要的朋友可以參考下
 
 

HTML5支持了Web Worker這樣的API,允許網頁在安全的情況下執行多線程代碼。不過Web Worker實際上受到很多限制,因為它無法真正意義上共享內存數據,只能通過消息來做狀態通知,所以甚至不能稱之為真正意義上的“多線程”。

Web Worker的接口使用起來很不方便,它基本上自帶一個sandbox,在沙箱中跑一個獨立的js文件,通過 postMessage和 onMessge來和主線程通信:

 

復制代碼代碼如下:

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);    //比較worker中傳回來的對象和主線程中的對象
    console.log(bundle);  //{message:'Hello world', id:1}
}

 

 

復制代碼代碼如下:

//in my.js
onmessage = function(evt){
    var data = evt.data;
    data.id++;
    postMessage(data); //{message:'Hello world', id:2}
}

 

得到的結果可以發現,線程中得到的data的id增加了,但是傳回來之后,并沒有改變主線程的bundle中的id,因此,線程中傳遞的對象實際上copy了一份,這樣的話,線程并沒有共享數據,避免了讀寫沖突,所以是安全的。保證線程安全的代價就是限制了在線程中操作主線程對象的能力。

這樣一個有限的多線程機制使用起來是很不方便的,我們當然希望Worker能夠支持讓代碼看起來具有同時操作多線程的能力,例如,支持看起來像下面這個樣子的代碼:

 

復制代碼代碼如下:

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

 

worker.run(function(bundle){
    //do sth in worker thread...
    this.runOnUiThread(function(bundle /*shared obj*/){
        //do sth in main ui thread...
    });
    //...
});

 

這段代碼里面,我們啟動一個worker之后,能夠讓任意代碼跑在worker中,并且當需要操作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__){
            //run on ui task
            var fn = (new Function("return "+ret.__UI_TASK__))();
            fn(ret.sharedObj);
        }else{
            self.sharedObj = ret.sharedObj;
            self._completes[ret.taskId](ret);
        }
    }
}

WorkerThread.prototype.run = function(task, complete){
    var _task = {__THREAD_TASK__:task.toString(), sharedObj: this.sharedObj, taskId: this._task_id};
    this._completes[this._task_id++] = complete;
    this._worker.postMessage(_task);
}

 

上面這段代碼定義了一個ThreadWorker對象,這個對象創建了一個運行thread.js的Web Worker,保存了共享對象SharedObj,并且對thread.js發回的消息進行處理。

如果thread.js中傳回了一個UI_TASK消息,那么運行這個消息傳過來的function,否則執行run的complete回調 我們看看thread.js是怎么寫的:

 

復制代碼代碼如下:

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

 

    if(data && data.__THREAD_TASK__){
        var task = data.__THREAD_TASK__;
        try{
            var fn = (new Function("return "+task))();

            var ctx = {
                threadSignal: true,
                sleep: function(interval){
                    ctx.threadSignal = false;
                    setTimeout(_run, interval);
                },
                runOnUiThread: function(task){
                    postMessage({__UI_TASK__:task.toString(), sharedObj:data.sharedObj});
                }
            }

            function _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,這是ui線程傳過來的需要worker線程執行的“任務”,由于function是不可序列化的,因此傳遞的是字符串,worker線程通過解析字符串成function來執行主線程提交的任務(注意在任務中將共享對象sharedObj傳入),執行完成后將返回結果通過message傳給ui線程。我們仔細看一下除了返回值returnValue以外,共享對象sharedObj也會被傳回,傳回時,由于worker線程和ui線程并不共享對象,因此我們人為通過賦值的方式同步兩邊的對象(這樣是否線程安全?為什么?)

可以看到整個過程其實并不復雜,這么實現之后,這個ThreadWorker可以有以下兩種用法:

 

復制代碼代碼如下:

var t1 = new WorkerThread({i: 100} /*shared obj*/);

 

        setInterval(function(){
            t1.run(function(sharedObj){
                    return sharedObj.i++;
                },
                function(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);
            }
            return sharedObj.i;
        }, function(r){
            console.log("t2>" + r.returnValue + ":" + r.error);
        });

 

這樣的用法從形式和語義上來說都讓代碼具有良好的結構,靈活性和可維護性。

好了,關于Web Worker的用法探討就介紹到這里,有興趣的同學可以去看一下這個項目:https://github.com/akira-cn/WorkerThread.js (由于Worker需要用服務器測試,我特意在項目中放了一個山寨的httpd.js,是個非常簡陋的http服務的js,直接用node就可以跑起來)。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲天堂免费在线| 4444欧美成人kkkk| 亚洲国产中文字幕久久网| 亚洲肉体裸体xxxx137| 亚洲日本成人女熟在线观看| 欧美多人乱p欧美4p久久| 亚洲成人1234| 日韩av免费在线看| 久久久久久久激情视频| 国产精品电影在线观看| 亚洲欧美一区二区三区情侣bbw| 欧美精品九九久久| 国产一区二区三区在线视频| 欧美大秀在线观看| 亚洲最大成人网色| 欧美日韩亚洲激情| 91网站免费观看| 97人人模人人爽人人喊中文字| 一区二区三区美女xx视频| 97婷婷大伊香蕉精品视频| 日韩成人激情视频| 日韩av在线高清| 亚洲精品少妇网址| 国产成人综合精品| 久久久久久久电影一区| 精品少妇一区二区30p| 久久久999精品视频| 亚洲欧美国产一区二区三区| 亚洲成人久久久久| 日本精品性网站在线观看| 欧美大尺度在线观看| 久久夜色精品国产| 97精品免费视频| 中文日韩电影网站| 91久久久久久久一区二区| 国内伊人久久久久久网站视频| 亚洲精品福利在线| 久久6免费高清热精品| 中文字幕日韩欧美精品在线观看| 久久精品中文字幕免费mv| 深夜福利亚洲导航| 中文字幕一区二区精品| 国产精品成久久久久三级| 久久综合伊人77777尤物| 国产免费观看久久黄| 国产成人精品一区二区三区| 日韩风俗一区 二区| 91九色蝌蚪国产| 亚洲精品国产精品国自产观看浪潮| 欧美激情精品久久久久久久变态| 丝袜亚洲另类欧美重口| 国产视频自拍一区| 亚洲a∨日韩av高清在线观看| 国产日韩精品一区二区| 亚洲欧美一区二区三区在线| 国产97在线|日韩| 国产精品中文字幕久久久| 在线播放亚洲激情| 自拍偷拍亚洲一区| 大伊人狠狠躁夜夜躁av一区| 久久精品国产清自在天天线| 色一情一乱一区二区| 久久久久久久久久久av| 欧美激情日韩图片| 国产精品视频久| 色av中文字幕一区| 亚洲乱码一区av黑人高潮| 97香蕉久久超级碰碰高清版| 久久成人国产精品| 日韩av在线免费观看一区| 欧美精品videosex性欧美| 国产精欧美一区二区三区| 午夜精品视频网站| 亚洲男人天堂2019| 亚洲成人教育av| 性夜试看影院91社区| 亚洲曰本av电影| 日韩av电影中文字幕| 麻豆精品精华液| 国产黑人绿帽在线第一区| 69视频在线免费观看| 欧美日韩在线看| 欧美日韩国产成人在线观看| 色悠悠久久久久| 亚洲最大av网站| 日本免费久久高清视频| 国产综合在线看| 国产69精品久久久久9| 欧美激情一区二区三级高清视频| 日韩成人在线播放| 亚洲精品福利视频| 91禁国产网站| 国a精品视频大全| 亚洲精品永久免费精品| 成人中文字幕在线观看| 国产成人激情小视频| 久久综合伊人77777尤物| 亚洲毛片在线免费观看| 欧美激情亚洲综合一区| 日韩av在线精品| 国产精品国语对白| 中文字幕亚洲激情| 成人免费视频97| 国产精品视频最多的网站| 九九久久国产精品| 久久精视频免费在线久久完整在线看| 亚洲欧洲高清在线| 久久精品91久久香蕉加勒比| 日韩av网站大全| 欧美成人免费网| 91久久久国产精品| 国产精品91久久久久久| 欧美精品videosex极品1| 亚洲欧美另类自拍| 韩剧1988免费观看全集| 亚洲欧美中文日韩在线v日本| 久久国内精品一国内精品| 成人伊人精品色xxxx视频| 国产精品91一区| 亚洲a中文字幕| 国产精品一区二区三区成人| 日韩小视频在线观看| 神马久久桃色视频| 亚洲影院色无极综合| 色综合视频一区中文字幕| 成人黄色片网站| 亚洲免费影视第一页| 亚洲国产精品女人久久久| 92看片淫黄大片看国产片| 国产精品国产三级国产aⅴ浪潮| 久久久亚洲国产| 日韩av影视综合网| 欧美日韩国产中字| 色樱桃影院亚洲精品影院| 亚洲一区二区自拍| 国模gogo一区二区大胆私拍| 亚洲精品suv精品一区二区| 欧美激情精品久久久久久| 啪一啪鲁一鲁2019在线视频| 日韩一中文字幕| 欧美激情欧美激情在线五月| 91成人国产在线观看| 日韩大胆人体377p| 久久国产精品视频| 亚洲在线第一页| 热re91久久精品国99热蜜臀| 91精品视频在线| 亚洲国产美女久久久久| 欧美日韩久久久久| 久久精品国产99国产精品澳门| 国内精品免费午夜毛片| 91色视频在线导航| 日韩av色综合| 国产精品美女无圣光视频| 性色av一区二区三区| 91青草视频久久| 国产一区二区三区视频免费| 色综合色综合久久综合频道88| 欧美国产第二页| 国产精品久久久久久久久粉嫩av| 国产suv精品一区二区| 国内精品久久久久久中文字幕| www.国产精品一二区| 国产精品黄色影片导航在线观看|