JavaScript如何实现多线程?

JavaScript025

JavaScript如何实现多线程?,第1张

JS为我们提供了一个Worker的类,它的作用就是为了解决这种阻塞的现象。当我们使用这个类的时候,它就会向浏览器申请一个新的线程。这个线程就用来单独执行一个js文件。

var worker = new Worker(js文件路径)

1

那么这个语句就会申请一个线程用来执行这个js文件。

当然,在主线程中有一些方法来实现对新线程的控制和数据的接收。在这里,我们只说比较常用的几个方法。

1 //postMessage(msg)

2 //postMessage方法把在新线程执行的结果发送到浏览器的js引擎线程里

3 worker.onmessage = function(){

4

7 setTimeout( function(){

8 worker.terminate()

9 //terminate方法用于关闭worker线程

10 },2000)

11

12 setTimeout( function(){

13 worker = new Worker("js/test22.js")

14 //再次开启worker线程

15 },3000)

在新线程中使用postMessage()方法可以向主线程中发送一些数据,主线程中使用worker的onmessage事件来接收这些数据,这样就实现了js的多线程执行和多线程之间数据的传递。

JS引擎的主线程负责执行代码,由于只有这一个线程,执行当然是同步的,即按照顺序来。另外,还有一个叫做任务队列的东西,所有的异步代码都是从队列当中来。

所以实际上我们会发现,JS根本不可能同时执行两个任务,本质上还是单线程。

在JS中,所谓的异步任务,有三种:

第一, 鼠标键盘事件触发,例如onclick、onkeydown等等

第二, 网络事件触发,例如onload、onerror等等

第三, 定时器,例如setTimeout、setInterval

一、线程和进程基本概念

进程:操作系统分配的占有CPU资源的最小单位。拥有独立的地址空间。

线程:安排CPU执行的最小单位。同一个进程下的所有线程,共享进程的地址空间。

简单讲,计算机就像工厂,进程是个大车间,计算机内部有很多个这样的大车间。线程是工人,每一个车间里的工人至少有一个。

为什么这么画呢?有点一个挨一个的效果呢?是因为以前我就老是疑惑进程或者线程运行时到底是并行?还是串行?

其实,在单CPU或单核的情况下,宏观上无论是进程也好,线程也罢,都是并行的。而在微观下,某一个具体的时刻,他们实际上都是串行的。在多CPU或多核的情况下,才是真正意义的并行。

二、线程和进程的关系、通性

关系:进程中包含着至少一个线程。在进程创建之初,就会包含一个线程,这个线程会根据需要,调用系统库函数去创建其他线程。但需要注意的是,这些线程之间是没有层级关系的,他们之间协同完成工作。在整个进程完成工作之后,其中的线程会被销毁,释放资源。

通性:都包含三个状态,就绪、阻塞、运行。通俗的讲,阻塞就是资源未到位,等待资源中。就绪,就是资源到位了,但是CPU未到位,还在运行其他。

三、线程的好处

既然,线程和进程是存在通性的,那么为什么操作系统还要设置线程这个单位,那就说说线程的几点好处:

1、在一个程序中,多个线程可以同步或者互斥并行完成工作,简化了编程模型;

2、线程较进程来讲,更轻;

3、线程虽然微观并行。但是,在一个进程内部,一个线程阻塞后,会执行这个进程内部的其他线程,而不是整体阻塞。从某种意义上,提高了CPU的利用率。

四、市面上的通用叫法

单线程与多线程,都指在一个进程内的单和多。不要笑我,之前真的不懂。心中那只小羊驼,奔过来,跑过去。还抬起了傲娇的眼睛,看了我一眼,呵呵~~~

五、javaScript单线程执行机制

1、 首先解释下,单线程和多线程。

什么是单线程?单线程就是一个进程中只有一个线程。程序顺序执行,前面的执行完,才会执行后面的程序。

什么是多线程?多线程就是一个进程中只有多个线程。在进程内部进行线程间的切换,由于每个线程执行的时间片很短,所以在感觉上是并行的。

2、那么为什么感觉上javaScript是多线程?而且还支持AJAX异步呢?AJAX是真正的异步吗?

先说明,从哪里可以得出javaScript是单线程。比如你页面一上来就alert(“hello world~”);只要你不关闭这个对话框,后续的js代码就不会再执行。因为,单线程就是这样一步一步的顺次执行,前面不执行完,后面不会执行。也就是说,在具体的某一时刻,只有一段代码在执行。

可是,JavaScript明明可以处理各种触发事件,感觉上是异步多线程啊。其实,它的原理是这样的,JavaScript单线程的执行浏览器的一个事件队列,要执行的函数和触发事件的回调函数都被放在这个队列中。比如,我点击率一下按钮,之后又将浏览器缩小了,那么这两个事件的回调函数就会顺次地被放在当前执行的“函数”之后,再一一执行。

那么,既然JavaScript是单线程,那么如何维护这个函数队列呢,他分身无术啊。这时候,就需要知道,浏览器可不是单线程。虽然,每一个window只有一个js引擎,但是浏览器是事件驱动的、异步的、多线程的。

浏览器内部有一个事件轮询(event loop),是一个大的内部消息循环,会轮询大的消息队列,并执行。也就是js要处理的事件队列,是浏览器维护的。

浏览器至少有四个线程(不同浏览器会有差异): js引擎线程、界面渲染线程、浏览器事件触发线程、http请求线程。

其实,到这里就说的很明白了。但是,又想到了延时函数(setTimeout)的例子,感觉上,因为没有阻塞执行,会感觉是异步,其实并不是。只是,js在执行到延时函数时,会触发浏览器的定时器,到设置时间,浏览器再将这个函数放入执行的函数队列,再由JavaScript引擎执行。都是在浏览器空闲了才会执行。

关于AJAX的异步,是真正的异步。同样的道理,在调用AJAX的时候,浏览器会开辟一个新的线程,去处理这个请求,得到响应后,如果这个请求有回调,会将这个回调再放入事件队列中。再由JavaScript引擎执行。

3、关于JavaScript的阻塞

浏览器虽然是多线程,但是由于JavaScript具有阻塞特性,无论外链还是内嵌脚本,在浏览器执行解释js脚本的时候,浏览器是不会去做别的事情的,比如渲染页面,而是直到js下载并执行完毕。

这样,js脚本的下载、解释执行,会反该页面的继续绘制,给用户带来不良的体验。所以,要对其优化,有如下几点:

a、将<script>内嵌和外链,在可以的情况下,放在<body>底部。注:对于css,浏览器是并行下载

b、在页面onload后,加载js

c、html5 <script>标签的defer属性,在页面加载完成后下载

d、使用创建<script>标签的方式,在页面加载完成后添加进去。

注:解决阻塞就是一句话,先让页面渲染完,再加载js。

六、Node.js单线程执行机制

脑子就像有问题一样。js都是单线程的了,node.js就是js实现的,还能是多线程?!!呵呵哒~

Node.js其实还不是真正意义上的js,他是借用了js语法实现的,达到真正意义的非阻塞服务端语言。但是他的运行机制,也是事件轮询 (Event Loop)。