HTML5之多线程(Web Worker)

yizhihongxing

HTML5的一个重要特性是支持多线程(Web Worker),这使得在浏览器执行JavaScript代码时可以使用多个线程加快程序运行速度,提升用户体验。

前置知识

在介绍Web Worker之前,需要先了解下JavaScript中的单线程和异步编程。JavaScript运行在浏览器端时只有一个主线程,在这个主线程中执行各种操作,包括用户交互和执行代码等等,因此当运行大量计算密集型操作或IO操作时,主线程可能会被阻塞,使得程序变得很慢。

为了解决这个问题,异步编程思想被引入JavaScript中,通过回调函数等方式实现异步操作,使程序能在等待IO操作时依然能够继续执行其他操作。

但是,JavaScript中的异步编程虽然能够缓解单线程带来的问题,但是仍然不能解决在计算密集型任务中单线程的阻塞问题。Web Worker就是为了解决这个问题而被设计出来的。

Web Worker的概念和使用

Web Worker是一种运行在浏览器后台的脚本,可以在主线程之外创建线程来执行JavaScript代码,不会影响主线程的运行和渲染。所以,在使用Web Worker时需要注意,worker中不能操作DOM,也不能访问主线程中的变量和函数等内容。

使用Web Worker非常简单。首先,我们需要通过new Worker()函数来创建一个worker对象,传入worker的脚本文件路径。例如:

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

在此之后,我们就可以向worker对象发送消息,以让它执行对应的逻辑。例如:

worker.postMessage('hello');

在worker的脚本文件中,我们需要用onmessage来监听从主线程传过来的消息,并根据消息内容执行相应的逻辑。例如:

onmessage = function(event) {
  console.log('from main thread: ' + event.data);
  postMessage('hello back');
}

在上述代码中,我们定义onmessage事件处理函数来接收主线程传来的消息,并打印到console中,然后再通过postMessage函数将一个”hello back”的消息发送回主线程。

最后,我们需要在主线程中通过监听message事件,来处理接收到的来自worker的消息:

worker.onmessage = function(event) {
  console.log('from worker: ' + event.data);
}

这样我们就完成了worker的创建、消息的发送和接收。

Web Worker的示例

接下来,我们通过两个示例来演示Web Worker的使用。

示例1:计算10000000以内质数的个数

我们为了演示多线程在计算密集型操作中的优势,我们来计算10000000以内质数的个数。首先,我们来看看单线程运行这个任务的效率:

function isPrime(n) {
  if (n <= 1) {
    return false;
  }
  for (var i = 2; i < n; i++) {
    if (n % i === 0) {
      return false;
    }
  }
  return true;
}

function countPrimes(start, end) {
  var count = 0;
  for (var i = start; i <= end; i++) {
    if (isPrime(i)) {
      count++;
    }
  }
  return count;
}

var start = new Date().getTime();
console.log('Total primes: ' + countPrimes(2, 10000000));
var end = new Date().getTime();
console.log('Elapsed time: ' + (end - start)/1000 + 's');

这段代码会输出在10000000以内的质数个数和程序运行的时间,由于我们是在单线程中进行运算,因此运算时间可能较长。

我们可以通过Web Worker来解决运算时间长的问题。首先我们来创建一个worker:

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

在worker.js文件中,我们需要实现countPrimes函数,代码如下:

function isPrime(n) {
  if (n <= 1) {
    return false;
  }
  for (var i = 2; i < n; i++) {
    if (n % i === 0) {
      return false;
    }
  }
  return true;
}

onmessage = function(event) {
  var data = event.data;
  var count = 0;
  for (var i = data.start; i <= data.end; i++) {
    if (isPrime(i)) {
      count++;
    }
  }
  postMessage(count);
}

我们定义onmessage事件处理函数来接收主线程传来的消息,并根据传过来的start和end范围计算其中的质数个数,最后将结果通过postMessage函数发送给主线程。

在主线程中,我们首先定义一个promise对象,用来监听工作线程发送过来的结果。当结果返回后,promise.then方法会执行回调函数来输出结果和运行时间:

var promise = new Promise(function(resolve, reject) {
  worker.onmessage = function(event) {
    resolve(event.data);
  }
});
promise.then(function(result) {
  var end = new Date().getTime();
  console.log('Total primes: ' + result);
  console.log('Elapsed time: ' + (end - start)/1000 + 's');
});

var start = new Date().getTime();
worker.postMessage({start: 2, end: 10000000});

多线程的代码和单线程中的代码对比,我们发现多线程的代码比单线程的代码更加复杂,但通过使用多线程,我们可以在执行计算密集型任务时提高运行效率。

示例2:通过Web Worker读取本地文件

在这个示例中,我们通过Web Worker来读取本地文件,我们在Web Worker中使用了FileReader读取文件并提取文件内容。主线程仅仅通过Web Worker向工作线程发送消息。

在主线程中,我们首先实例化一个worker对象:

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

在Web Worker中,我们可以使用FileReader的api读取文件内容,代码如下:

onmessage = function(event) {
  var file = event.data;
  var reader = new FileReader();
  reader.onload = function(event) {
    var data = event.target.result;
    postMessage(data);
  };
  reader.readAsText(file);
};

在主线程中,我们首先定义一个input元素和一个button元素,用户可以使用这些元素来选择文件。在选择文件后,我们通过Web Worker来读取此文件的内容:

var input = document.createElement('input');
input.type = 'file';
document.body.appendChild(input);

var button = document.createElement('button');
button.textContent = 'Read File';
document.body.appendChild(button);

button.onclick = function() {
  var file = input.files[0];
  var promise = new Promise(function(resolve, reject) {
    worker.onmessage = function(event) {
      resolve(event.data);
    };
  });
  promise.then(function(result) {
    console.log(result);
  });
  worker.postMessage(file);
};

通过以上的代码,我们可以通过Web Worker读取本地文件,节约了主线程所需的时间和计算功耗。

总结

  • Web Worker是一个能够让JavaScript中使用多线程的API。
  • Web Worker能够在浏览器中创建线程,协同工作线程和主线程,同时提高程序运算效率并降低程序响应时间。
  • 在Web Worker中,不支持DOM和主线程中的变量和函数等内容,因此Web Worker使用场景比较有限。
  • 通过两个实例的演示,可以发现Web Worker在计算密集型任务执行中具有很好的优势,可以大大提升程序的运行效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:HTML5之多线程(Web Worker) - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C++实现线程同步的四种方式总结

    C++实现线程同步的四种方式总结 在多线程程序中,线程同步是一个非常重要的问题。为了保证多个线程的正确性和稳定性,我们需要采用线程同步措施,这样才能确保多个线程同时处理共享资源时不会出现数据读写冲突等问题。C++中实现线程同步主要有四种方式:互斥锁、条件变量、信号量和读写锁。 一、互斥锁(Mutex) 1. 互斥锁概念 互斥锁是最基本的线程同步机制。一段代码…

    多线程 2023年5月16日
    00
  • js异步接口并发数量控制的方法示例

    接下来我将详细讲解“js异步接口并发数量控制的方法示例”的完整攻略。 什么是异步接口 异步接口是指在请求接口的时候,不会阻塞后面的代码执行,而是会进行异步回调处理,等到服务器返回结果之后再执行接下来的操作。与之相对的是同步接口,同步接口会阻塞后面的代码执行,直到服务器返回结果之后才能继续执行下一步操作。 在Javascript中,我们通常使用XMLHttpR…

    多线程 2023年5月16日
    00
  • Java面试题冲刺第十二天–数据库(2)

    来给大家详细讲解一下“Java面试题冲刺第十二天–数据库(2)”的完整攻略。 一、数据库相关知识点 本篇文章主要涉及以下数据库相关知识点: 数据库事务 数据库锁 事务的隔离级别 数据库优化 二、数据库事务 数据库事务可以保证多个对数据库的操作是一个原子性操作,即只要其中有一个操作失败,整个事务都将回滚。 在Java中使用JDBC进行事务控制时,需要使用以下…

    多线程 2023年5月17日
    00
  • java多线程:基础详解

    Java多线程:基础详解攻略 什么是线程? 在计算机科学中,线程是指一个进程内部的单个执行流程。一个进程可以拥有多个线程,各个线程共享该进程的内存空间和系统资源,但每个线程拥有自己的程序计数器(PC)、栈和局部变量等。因此,多线程可以使程序在并发情况下更高效地运行。 如何创建线程? Java提供了两种方式来创建线程: 1.继承Thread类 在Java中,我…

    多线程 2023年5月17日
    00
  • python单线程下实现多个socket并发过程详解

    本文将为大家详细讲解如何在 Python 单线程下实现多个 socket 并发,具体内容如下: 1. 什么是 socket socket 是计算机上的一个抽象概念,就像打电话需要电话机一样,在网络中发送信息需要由 socket 传递和接收。在 Python 编程语言中,socket 是标准库中用于实现网络通信的一种方式。 2. 单线程下实现多个 socket…

    多线程 2023年5月17日
    00
  • DB2和 Oracle的并发控制(锁)的比较

    DB2和Oracle的并发控制(锁)的比较 什么是并发控制(锁)? 并发控制是指在多个用户同时对数据库进行读写操作时,确保这些操作能够顺利执行而不产生冲突的一种技术。一般来说,当多个用户同时对数据库进行读写时,会产生资源竞争和数据一致性问题,而锁技术可以帮助解决这些问题。 DB2与Oracle的并发控制锁机制 DB2的并发控制锁机制 DB2支持多种类型的锁,…

    多线程 2023年5月17日
    00
  • IOS开发之多线程NSThiread GCD NSOperation Runloop

    IOS开发之多线程 什么是多线程 多线程是指使用多个并发执行的线程来完成多个任务或者同时处理不同部分的问题,以达到提高程序性能、提高对用户的响应速度和实现更复杂的功能等目的。 在IOS开发中,多线程机制能够让我们在应用中去执行长时间运行的非UI操作,保持主线程的响应性,以增强应用的用户体验。 多线程的三种方式 1. NSThread NSThread是基于线…

    多线程 2023年5月16日
    00
  • 详解Java多线程与并发

    详解Java多线程与并发攻略 Java多线程与并发是Java编程中非常重要的一个部分,它可以提高程序的效率和运行速度。本文将详细介绍Java多线程与并发的相关知识和技巧。包括线程创建、线程安全、synchronized关键字、volatile关键字等。 线程创建 Java创建线程的方法有两种: 继承Thread类并重写run()方法。 示例代码: publi…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部