zoukankan      html  css  js  c++  java
  • Web Worker多线程

    背景:

    • Js语言采用的是单线程模型
    • 随着计算机能力增强,多核CPU的出现,单线程带来很大的不便,无法充分发挥计算机的计算能力

    Web Worker的作用:

    • 为Javascript创造多线程环境,允许主线程创建Worker线程,将一些任务分配给后者运行
    • 主线程运行的同时,Worker线程在后台运行,两者互不干扰
    • 可以降一些计算密集型或高延迟的任务,分给Worker线程负担,主线程(通常负责UI交互)就会很流畅,不会被阻塞或拖慢
    • Worker线程一旦新建成功,就会始终运行,不会被主线程上的活动打断(比如用户点击按钮、提交表单)。这样有利于随时响应主线程的通信。但是,这也造成了Worker比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

    注意点:

    • 同源策略:分配给Worker线程运行的脚本,必须与主线程的脚本文件同源
    • DOM限制:Worker线程所在的全局对象与主线程不一样,无限读取主线程所在的网页的DOM对象,也无法使用documentwindowparent这些对象。但是Worker线程可以使用navigator对象和location对象
    • 通信联系:Worker线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。(postMessage发送消息,onmessage监听消息)
    • 脚本限制:Worker线程不能执行alert()和confirm(),但可以使用XMLHttpRequest对象发出AJAX请求
    • 文件限制:Worker线程无法读取本地文件(file://这类),它所敬爱在的脚本必须来自网络

    基本用法:

    //主线程
    var worker = new Worker(‘./worker.js')
    //向Worker发消息
    worker.postMessage('hello world')
    worker.postMessage({method:'echo', args:['work']})
    //监听消息
    worker.onmessage = function(event) {
        console.log('Received message' + event.data)
        doSomething()
    }
    
    function doSomething() {
     //执行任务
     worker.postMessage('Work done!')
     //结束线程
     worker.terminate()
    }
    
    //子线程
    //发送消息
    this.postMessage('get it!')
    
    //self代表子线程自身,即子线程的全局对象。因此,等同于下面两种写法
    self.addEventListener('message', function (e) {
      self.postMessage('You said: ' + e.data);
    }, false);
    
    //写法一
    //监听消息
    this.addEventListener('message', function(event) {
        this.postMessage('You said' + event.data)
    }, false)
    
    // 写法二
    addEventListener('message', function (e) {
      postMessage('You said: ' + e.data);
    }, false);
    
    //根据主线程发来的数据,Worker 线程可以调用不同的方法,下面是一个例子。
    
    self.addEventListener('message', function (e) {
      var data = e.data;
      switch (data.cmd) {
        case 'start':
          self.postMessage('WORKER STARTED: ' + data.msg);
          break;
        case 'stop':
          self.postMessage('WORKER STOPPED: ' + data.msg);
          self.close(); // Terminates the worker.
          break;
        default:
          self.postMessage('Unknown command: ' + data.msg);
      };
    }, false);
    

    Worker加载脚本

    //加载单个
    importScripts('script1.js')
    //加载多个
    importScripts('script2.js', 'script3.js')
    
    错误处理
    worker.onerror(function (event) {
        console.log([
            'ERROR: Line', e.lineno, 'in ', e.filename, ':', e.message
            ].join('')
        )
    })
    //或者
    worker.addEventListener('error', function(event){
    //...
    })
    
    关闭Worker
    //使用完毕,为了节省系统资源,要及时关闭Worker
    
    //主线程
    worker.terminate()
    //Worker线程
    self.close()
    

    数据通信

    • 主线程与Worker之间的通信内容,可以是文本、对象。这种通信是深拷贝关系,Worker对通信内容修改,不影响到主线程。(浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给Worker,后者再将它还原)
    • 主线程与Worker之间,也可以交换二进制数据,比如File、Blob、ArrayBuffer等

    注意点:拷贝方式发送二进制数据会造成性能问题。比如主线程向Worker发送一个500MB的文件,默认情况下浏览器会生成一个源文件的拷贝。
    为了解决这个问题,JavaScript允许主线程把二进制数据直接转移给子线程,但是一旦转移,主线程就无法再使用这些二进制数据了,这是为了防止出现多个线程同时修改数据的麻烦局面。
    这种转移数据的方法,叫做Transferable Objects。这使主线程可以快速将数据交给Worker,对于影像处理、声音处理、3D运算等就非常方便了,不会产生性能负担。

    //直接转移数据的控制权,使用下面的写法:
    worker.postMessage(arrayBuffer, [arrayBuffer])
    //例如
    var ab = new ArrayBuffer(1)
    worker.postMessage(ab, [ab])
    

    同页面载入Web Worker

    <!DOCTYPE html>
    <html>
        <body>
        <!--worker线程-->
        <script id = "worker" type="app/worker">
            addEventListener('message', function(){
                postMessage('some message')
            }, false)
        </script>
        <!--主线程-->
        <script>
            var blob = new Blob([document.querySelector('#worker').textContent])
            var url = window.URL.createObjectURL(blob)
            var worker = new Worker(url)
            worker.onmessage = function(e) {
            //e.tata === 'some message'
            }
        
        </script>
        </body>
    </html>
    

    参考链接:http://www.ruanyifeng.com/blog/2018/07/web-worker.html

  • 相关阅读:
    Direct2D 变换
    DWrite 文字
    Windows基础窗体编程
    .net delegate(委托类型)
    详说new和overrid区别
    类与结构区别
    IIS的Gzip压缩
    ASP.NET 状态服务和session丢失问题解决方案
    Fiddler使用
    Castle系列教程(转)
  • 原文地址:https://www.cnblogs.com/HappyYawen/p/14324226.html
Copyright © 2011-2022 走看看