worker多线程的使用与理解

JavaScript在浏览器环境中是单线程的,为了避免并发操作带来的冲突,如DOM操作。WebWorker提供了多线程能力,允许主线程创建子线程执行计算任务,互不干扰。子线程通过message事件监听和通信,主线程则通过onmessage接收返回结果。文章通过案例展示了如何创建和使用WebWorker,以及关闭线程的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        JavaScript是单线程的,并不是说它是单线程语言,只能说在浏览器中运行是单线程的,单线程会免去许多麻烦,比如说,有两个线程同时进行DOM操作,一个是在父级下添加子元素,一个是删除这个父级元素,这样会冲突的。但是呢?浏览器是多线程的,浏览器打开多个标签页依旧运行良好,为了充分利用,就有了 Web Worker ,它为 JavaScript 创造多线程环境,允许主线程创建子线程,将一些任务分配给子线程运行。在主线程运行的同时,子线程在后台运行,两者互不干扰。等到子线程完成计算任务,再把结果返回给主线程。但这并不是说,JavaScript就不是单线程了,要知道,子线程是主线程控制的。

单线程证明

案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Worker多线程</title>
</head>
<body>
  <button  onclick="start()">开始</button>
  <button onclick="stop()">停止</button>
  <script type="text/javascript">
    function start(){
        let num = 0
        setInterval(() => {
        num++
        console.log(num)
    }, 500);
    }
    function stop(){
       alert('只要不点击暂停,这个alert任务就没有结束')
    }
  </script>
</body>
</html>

结果:

     每0.5秒在队列中添加一个任务,点击停止时,添加了一个alert任务,定时器这个不断添加的任务就得排队等待不再继续累加。


 Web Worker的使用

1.主线程创建worker。 

var worker = new Worker('work.js');

 2.主线程调用worker.postMessage()方法,向 Worker 发送内容,可以理解为参数。

worker.postMessage( 'a' );

worker.postMessage([1,2,3,4,5]);

worker.postMessage({

        name:'zhangsan',

        age:20

});

3.子线程通过message来监听主线程传递的信息 

this.addEventListener('message', function (e) {

    this.postMessage('e' + e.data); //传递过来的信息

  }, false);

//或者

onmessage = function(e){

    console.log('e',e.data); //传递过来的信息

}

4.主线程接收子线程返回的数据 

worker.onmessage = function(e){

         console.log('e',e)

 }

//或者

worker.addEventListener('message', function (e) {

        console.log('e',e.data)

 }, false);

5.关闭线程,节约资源

self.close()

worker.terminate()

(详情见下边案例)

<body>
  <button  onclick="start()">开始</button>
  <button onclick="stop()">停止</button>
  
  <script type="text/javascript">
    function start(){
       var worker = new Worker('worker.js');
       worker.postMessage(0);//将复杂计算交给子线程,可以理解为给参数让子线程去操作。
       worker.onmessage = function(e){
           console.log('主线程打印',e.data);//接收子线程返回来的数据,这个打印是主线程打印。   
       }
    }
    function stop(){
       alert('只要不点击暂停,这个任务就没有结束,定时器每0.5秒添加的任务需要排队等待。')
    }
  </script>
</body>

worker.js文件

// 响应主线程发过来的数据进行处理
onmessage = function(e){
    // console.log('e',e.data)
    var num = e.data;//接收从主线程传过来的值
    setInterval(() => {
        num++
        console.log(num)
        postMessage(num);//把计算结果传回给主线程
    }, 500); 
}

结果:

        主线程中走alert任务的时候,主线程打印已经停止,子线程继续再执行,不受影响。当alert任务点击确定结束,堆积的打印任务一口气都“吐”了出来。


关闭worker线程的方式

        1.worker线程(子线程)自己关闭:self.close();

        2.主线程控制关闭:worker.terminate();

案例:-----worker.terminate()

<body>
  <button onclick="start()">开始</button> 
  <script type="text/javascript">
    function start(){
       var worker = new Worker('worker.js');
       worker.postMessage(0);
       worker.onmessage = function(e){
           if(e.data == 5){
                worker.terminate();	
                console.log('主线程打印:worker线程结束')
           }
       }
    }
  </script>
</body>

结果:

案例: -----self.close() 

worker.js

onmessage = function(e){
    var num = e.data;//接收从主线程传过来的值
    setInterval(() => {
        num++
        console.log(num)
        if(num == 5){
            self.close() 
        }
        postMessage(num);//把计算结果传回给主线程
    }, 500);
}

 

               结束。 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天命爱心职责~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值