js进程和线程的区别
日期:2019-03-01
来源:程序思维浏览:2533次
在理解进程和线程概念之前首选要对并发有一定的感性认识,如果服务器同一时间内只能服务于一个客户端,其他客户端都再那里傻等的话,可见其性能的低下估计会被客户骂出翔来,因此并发编程应运而生,并发是网络编程中必须考虑的问题。实现并发的方式有多种:比如多进程、多线程、IO多路复用。
多进程
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
Linux系统函数fork()可以在父进程中创建一个子进程,这样的话,在一个进程接到来自客户端新的请求时就可以复制出一个子进程让其来处理,父进程只需负责监控请求的到来,然后创建子进程让其去处理,这样就能做到并发处理。
# -*- coding:utf-8 -*-
import os
print('当前进程:%s 启动中 ....' % os.getpid())
pid = os.fork()
if pid == 0:
print('子进程:%s,父进程是:%s' % (os.getpid(), os.getppid()))
else:
print('进程:%s 创建了子进程:%s' % (os.getpid(),pid ))
输出结果:
当前进程:27223 启动中 ....
进程:27223 创建了子进程:27224
子进程:27224,父进程是:27223
fork函数会返回两次结果,因为操作系统会把当前进程的数据复制一遍,然后程序就分两个进程继续运行后面的代码,fork分别在父进程和子进程中返回,在子进程返回的值pid永远是0,在父进程返回的是子进程的进程id。
多线程
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
线程和进程各自有什么区别和优劣呢?
进程是资源分配的最小单位,线程是程序执行的最小单位。
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
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)。
多进程
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
Linux系统函数fork()可以在父进程中创建一个子进程,这样的话,在一个进程接到来自客户端新的请求时就可以复制出一个子进程让其来处理,父进程只需负责监控请求的到来,然后创建子进程让其去处理,这样就能做到并发处理。
# -*- coding:utf-8 -*-
import os
print('当前进程:%s 启动中 ....' % os.getpid())
pid = os.fork()
if pid == 0:
print('子进程:%s,父进程是:%s' % (os.getpid(), os.getppid()))
else:
print('进程:%s 创建了子进程:%s' % (os.getpid(),pid ))
输出结果:
当前进程:27223 启动中 ....
进程:27223 创建了子进程:27224
子进程:27224,父进程是:27223
fork函数会返回两次结果,因为操作系统会把当前进程的数据复制一遍,然后程序就分两个进程继续运行后面的代码,fork分别在父进程和子进程中返回,在子进程返回的值pid永远是0,在父进程返回的是子进程的进程id。
多线程
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
线程和进程各自有什么区别和优劣呢?
进程是资源分配的最小单位,线程是程序执行的最小单位。
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
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)。
- 上一篇:前端面试必问语义化标签的好处
- 下一篇:js的设计模式和模块模式一看便懂
精品好课