本文原创:zhaojiaojiao
进程
进程是动态的,一般由程序、数据集合和进程控制块三部分组成,程序用来描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;进程控制块(PCB)包含进程的描述信息和控制信息,是进程存在的唯一标识
PCB
- 作用是描述进程,对进程进行有效的控制和管理;具体体现为,进程创建时,系统会创建对应的PCB,当进程状态发生变化时,系统会将状态记录在PCB中,当进程执行结束时,系统回收其PCB
- 记录的信息主要有:进程标识符、进程当前状态、进程队列指针、程序和数据地址、进程优先级、CPU现场保护区、通信关系、家族关系、资源清单(不同操作系统的进程控制块结构不同)
进程状态
- 就绪状态:具备执行条件
- 执行状态:正在运行的状态
- 阻塞状态:暂时无法执行下去
线程
线程是程序执行中的一个单一的顺序控制流程,是CPU调度的最小单位,一个进程有一个或者多个线程,各个线程之间共享进程的内存空间,一个标准的线程由线程ID、当前指令指针(PC),寄存器和堆栈组成
线程的栈被自动分配到进程的内存空间中
线程和进程的区别
线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位
一个进程由一个或者多个线程组成,线程是一个进程中代码的不同执行路线
进程之间相互独立,但是同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(打开文件和信号),某进程内的线程在其它进程中不可见
调度和切换:线程上下文切换比进程上下文切换要快的多
Node.js中的进程和线程
进程
Process模块
process 对象是一个全局变量,它提供有关当前 Node.js 进程的信息并对其进行控制。 作为一个全局变量,它始终可供 Node.js 应用程序使用,无需使用 require()。 它也可以使用 require() 显式地访问(摘自Node Process):
const process = require('process');
通过process我们可以设置或获取进程的信息,如下所示:
const http = require('http');
const server = http.createServer();
server.listen(3000,()=>{
process.title='开启进程';
console.log('进程id',process.pid)
})
控制台输出
进程id 77193
进程的创建
Node中提供了child_process模块用来创建子进程,下面列出了创建异步进程的方法,其他的方法可查看 child_process介绍
child_process.exec:可以衍生一个 shell 然后在该 shell 中执行command,并缓冲任何产生的输出child_process.execFile:与exec类似,区别是默认情况下是不能衍生shell的child_process.fork:是child_process.spawn()的一个特例,专门用于衍生新的 Node.js 进程,衍生的 Node.js 子进程独立于父进程,但两者之间建立的 IPC 通信通道除外。 每个进程都有自己的内存,带有自己的 V8 实例。 由于需要额外的资源分配,因此不建议衍生大量的 Node.js 子进程。child_process.spawn:使用给定的command衍生一个新进程,并带上args中的命令行参数
child_process.exec() 和 child_process.execFile() 方法还允许指定可选的 callback 函数,当子进程终止时会被调用。
下面是创建子进程的示例:
process.js
const http = require('http');
const url = require('url');
const fork = require('child_process').fork;
let server = http.createServer(function(req, res) {
let pathname = url.parse(req.url).pathname;
if (pathname == '/time') {
let child = fork('./childProcess.js');
child.send('start');
child.on('message', (msg) => {
console.log('get result: ', new Date(+msg));
res.end(msg);
});
}
});
server.listen(3000, '127.0.0.1');
childProcess.js
const http = require('http');
let getTime = () => {
return Date.now() + '';
};
process.on('message', (msg) => {
console.log('子进程接收到的:', msg);
let time = getTime();
process.send(time);
})
在浏览器中访问:http://127.0.0.1:3000/time,会有如下的展示:
控制台的输出如下:
线程
在Node的10.5.0版本中,worker_threads 为Node提供了多线程的能力,与 child_process 或 cluster 不同, worker_threads 可以共享内存。
模块中常用到的:
isMainThread:是否是主线程parentPort:可以用来与主线程交换信息,可通过parentPort.postMessage()发送的信息会在主线程中通过worker.on('message')接收workerData:通过主线程中传递过来的数据, 它可以是任意的JavaScript值,通过主线程构造函数中的选项对象的workerData传递(拷贝传递)MessagePort 类:线程通信,继承自 EventEmitter
MessageChannel类: 用于创建异步、双向通信的通道实例。
Worker类:在主线程中创建子线程,第一个参数为 filename,表示子线程执行的入口
const {
isMainThread,
parentPort,
workerData,
Worker
} = require('worker_threads');
if (isMainThread) {
const worker = new Worker(__filename, { workerData: 1 });
worker.on('message', msg => {
console.log(`main: receive ${msg}`);
worker.postMessage('parent')
});
} else {
console.log(`worker: workerDate ${workerData}`);
parentPort.on('message', msg => {
console.log(`worker: receive ${msg}`);
});
parentPort.postMessage(workerData);
}
相关输出如下:
欢迎计算机前端相关领域小伙伴加入我们,具体的招聘信息可进入公众号查看,欢迎关注。
本文由博客一文多发平台 OpenWrite 发布!