单线程与多线程概念
单线程
定义:
单线程指的是程序中只有一条执行路径,即程序按顺序一行一行地执行代码。在任何给定的时刻,只有一个任务在执行。
特点:
- 顺序执行:程序按照代码的顺序从上到下依次执行。
- 简单性:由于没有并发执行的代码路径,因此编程和调试相对简单。
- 资源消耗少:不需要额外的线程管理开销。
- 执行效率低:在处理耗时操作时,整个程序会被阻塞,无法执行其他任务。
应用场景:
- 一些简单的、不需要并发处理的程序,如简单的计算器。
- 实时性要求不高的任务。
多线程
定义:
多线程指的是程序中存在多条执行路径,即可以同时执行多个任务。每个任务称为一个线程,这些线程共享程序的内存空间和系统资源。
特点:
- 并发执行:多个线程可以同时运行,提高程序的执行效率。
- 资源共享:线程可以访问程序中的共享数据(需要同步机制来避免数据竞争)。
- 线程间通信:线程之间可以通过共享内存、消息传递等方式进行通信。
- 复杂性增加:编程和调试多线程程序相对复杂,需要考虑线程同步、死锁等问题。
- 开销增加:创建和管理线程需要一定的系统资源开销。
应用场景:
- 需要同时处理多个任务的情况,如Web服务器、多线程下载等。
- 实时性要求高的任务,如游戏开发中的动画渲染和输入处理。
- 复杂的计算任务,可以通过多线程实现并行计算,提高计算效率。
web worker概念
一、定义与背景
- 定义:Web Worker是一个在浏览器后台线程中运行的JavaScript脚本,它独立于主线程执行,可以处理耗时的计算任务而不影响页面的性能和响应速度。
- 背景:在单线程的JavaScript环境中,长时间运行的任务会阻塞主线程,导致用户界面无响应。为了解决这个问题,Web Worker提供了一种在后台线程中运行脚本的机制,以实现并行处理。
二、工作原理
- 创建Worker:首先,需要创建一个JavaScript文件,用于编写Web Worker的逻辑。然后,在主线程的JavaScript代码中,使用
new Worker()
构造函数创建一个Web Worker实例,并指定该Worker文件的路径。 - 消息传递:主线程和Web Worker之间通过消息传递进行通信。主线程可以使用
postMessage()
方法向Web Worker发送消息,而Web Worker则使用相同的方法将结果发送回主线程。这种通信方式是基于事件的,即当消息到达时,会触发相应的事件处理程序。 - 执行任务:在Web Worker的JavaScript文件中,编写需要在后台执行的任务逻辑。这可以包括耗时的计算、数据处理或其他操作。当Web Worker接收到主线程发送的消息时,它会执行相应的任务,并将结果发送回主线程。
三、特点与限制
- 特点:1. 并行处理:Web Worker允许在后台线程中执行脚本,实现并行处理,从而提高应用程序的性能。2. 独立性:Web Worker运行在独立的线程中,无法直接访问主线程的DOM、全局变量和大多数浏览器API。这种独立性确保了Web Worker不会干扰主线程的运行。3. 消息传递:主线程和Web Worker之间通过消息传递进行通信,这种通信方式是基于事件的,具有异步性。
- 限制:1. 无法直接操作DOM:由于Web Worker运行在独立的线程中,因此无法直接访问或修改DOM。如果需要更新页面内容,必须通过消息传递将结果发送回主线程,由主线程来更新DOM。2. 全局作用域不同:Web Worker的全局作用域是
WorkerGlobalScope
,而不是主线程的window
对象。因此,一些在主线程中可用的全局变量和函数在Web Worker中可能不可用。3. 浏览器兼容性:虽然大多数现代浏览器都支持Web Worker,但一些较旧的浏览器(如Internet Explorer的某些版本)可能不支持或仅支持部分功能。
四、应用场景
- 复杂计算:对于需要执行复杂计算的任务(如图像处理、视频解码、大规模数据处理等),可以使用Web Worker在后台线程中执行这些计算,从而避免阻塞主线程并提高应用程序的响应速度。
- 耗时操作:对于耗时较长的操作(如文件读取、网络请求等),可以使用Web Worker在后台线程中执行这些操作,以便用户可以继续与页面进行交互。
- 并行处理:在需要并行处理多个任务的情况下(如多线程下载、并发请求等),可以使用Web Worker来创建多个后台线程并同时执行任务。
web worker实战
该实战基于vue框架基础,需下载安装 worker-loader
.vue文件页面代码
使用new Worker方法创建一个worker实例,方法中需要配置你的web worker的js文件的路径,我这里是@/utils/worker1.js,然后可以监听message动作(onmessage),打印出js文件的发送的message信息
<template>
<div>
</div>
</template>
<script>
export default {
name: 'APP',
data () {
return {
}
},
methods: {
testWorker () {
const worker1 = new Worker(new URL('@/utils/worker1.js', import.meta.url))
worker1.onmessage = function (e) {
console.log(e)
}
}
},
created () {
},
mounted () {
this.testWorker()
}
}
</script>
<style lang="less" scoped>
/* @import url(); 引入css类 */
</style>
worker1.js文件代码
使用web worker的全局对象self进行发送message动作(postMessage)
self.postMessage('进行多线程1')
打印结果
可以看到控制台打印出了messageEvent对象,其中data为发送的message,而这个动作的是web worker开辟的多线程中完成的,不是在js主线程
web worker多线程利用
知道了可以利用多线程,我们就可以将多个耗时的js代码放入不同的web worker的js文件中,使其能一起进行执行
.vue文件页面代码修改
加入了三个web worker的js文件,多线程执行文件的代码
<template>
<div>
</div>
</template>
<script>
// import worker1 from '@/utils/worker1.js'
export default {
name: 'APP',
data () {
return {
}
},
methods: {
testWorker () {
const worker1 = new Worker(new URL('@/utils/worker1.js', import.meta.url))
const worker2 = new Worker(new URL('@/utils/worker2.js', import.meta.url))
const worker3 = new Worker(new URL('@/utils/worker3.js', import.meta.url))
worker1.onmessage = function (e) {
console.log(e.data)
}
worker2.onmessage = function (e) {
console.log(e.data)
}
worker3.onmessage = function (e) {
console.log(e.data)
}
}
},
created () {
},
mounted () {
this.testWorker()
}
}
</script>
<style lang="less" scoped>
/* @import url(); 引入css类 */
</style>
创建多个js文件放入耗时的js代码
调用文件中一个耗时的函数并打印出执行时间
function fb (n) {
if (n === 1 || n === 2) {
return 1
}
return fb(n - 1) + fb(n - 2)
}
console.time('fb执行时间1')
fb(43)
console.timeEnd('fb执行时间1')
self.postMessage('进行多线程1')
//worker1.js
function fb (n) {
if (n === 1 || n === 2) {
return 1
}
return fb(n - 1) + fb(n - 2)
}
console.time('fb执行时间2')
fb(43)
console.timeEnd('fb执行时间2')
self.postMessage('进行多线程2')
//worker2.js
function fb (n) {
if (n === 1 || n === 2) {
return 1
}
return fb(n - 1) + fb(n - 2)
}
console.time('fb执行时间3')
fb(43)
console.timeEnd('fb执行时间3')
self.postMessage('进行多线程3')
//worker3.js
打印结果
可以看到三个js中的函数同时执行,差不多同一刻一起打印出来,实现了多线程的应用
希望大家能学习到,一起交流讨论
版权归原作者 爱编程的吉米 所有, 如有侵权,请联系我们删除。