-
Chrome 浏览器的线程模型是怎样的? (操作系统=国家 内存空间 围圈厂子(进程空间 Chrome多个进程)) 生产线(线程)
- 程序: 计算机可以执行的代码, 存在于磁盘中, 一个程序有多个进程
- 进程: 把程序调入到计算机的内存中, 准备执行, 是活动的, 等待被CPU执行 (分配内存空间, CPU处理)
- 线程: CPU执行进程代码的基本单位--生产任务(生产线) 多个线程之间互不影响
-
进程和线程的关系
- 进程是操作系统分配内存的基本单位 (武器工厂圈地造武器, 是国家允许的基本单位)
- 线程必须处于进程内部(每一个武器厂的生产线就是一个线程, 国家不可能直接给你生产线分配内存, 而是由线程调度)
一个进程至少有一个线程, 也可以有多个 (8G内存可以大致创建 4000个线程, 创建2000个左右就会卡死)
-
多个线程之间是怎么工作的?
- 多个线程之间是并发执行的 (宏观上同时执行的, 微观上是同步的 时间片)
- Chrome里面的线程: JS引擎线程, GUI线程, 异步HTTP请求线程, 定时器线程, 事件处理线程
-
输入一个URL
- Chrome中发起http请求最多可以使用6个并发的线程
- chrome中负责向页面中执行绘制任务的只有一个线程- GUI线程 (只有上面的绘制才能绘制下面的, 所以一个就够了, 多了碍事) UI主线程
- 根本解决之道: 创建一个新的线程, 去执行耗时的js任务 JavaThread = new Thread
- H5提供类似创建新线程的机制 new Worker('wkr.js') //工人线程 专门用来执行耗时操作的, 与UI主线程并发执行, 所以UI主线程不会卡主
-
Worker的天然缺陷
- 不允许接触任务的BOM和DOM对象 (window, document)
- 原因: 只能有一个渲染线程, worker允许参与GUI的话, 浏览器GUI绘画会乱掉(同时渲染会出问题)
-
worker的用途 (真实的项目中用到的地方比较少)
- 非常耗时的且与DOM操作无关的时候, 会用到
-
UI主线程可以给Worker传递数据 --- 发消息, Worker线程可以给UI主线程传递数据 --- 接收消息
- UI线程发送消息/接收消息
worker.postMessage(value) worker.onmessage=function(event) {console.log(event.data)}
- Worker线程接收消息/发送消息
onmessage = function(event) { console.log(event.data) postMessage('stringData') }
- UI线程发送消息/接收消息
-
worker线程是不能再创建子线程worker的, worker只能与GUI主线程进行通信 (比Java的thread更加单纯)
总结:- Worker本质上是一个线程, 在UI主线程之外并发执行的线程, 用来执行耗时的JS任务
- 缺陷: 不能操作DOM和BOM, 只能和UI主线程发消息
- 实际上的复杂操作由服务器完成, 服务器比浏览器快多了
-
H5测试代码 (需要在服务器上运行, 本地运行会出错)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>worker 和 GUI 线程之间的通信</title>
</head>
<body>
<input type="number" id="num" value="12" min="0" max="1000">
<button id="startBtn">开始开启worker</button>
<p id="result"></p>
<script>
var btn = document.getElementById('startBtn');
btn.onclick = function() {
var value = document.getElementById('num').value;
var worker = new Worker('worker_calculate.js');
// UI线程给worker传递消息数据
worker.postMessage(value)
worker.onmessage = function(event) {
var data = event.data;
document.getElementById('result').innerHTML = data;
}
// UI主线程接收主线程传递的消息
}
</script>
<button onclick="console.log(1111)">button1</button>
<button onclick="console.log(222)">button2</button>
</body>
</html>
- worker_cakculate.js
/*Worker接收GUI主线程的发送的消息, 接收到消息后才能开始运算*/
console.log('Worker线程待命中')
// worker中 直接写onmessage方法即可
onmessage = function(event) {
var n = event.data; // 表示传递过来的数据
var value = parseInt(n);
console.log('---------从GUI主线程获取到的数据: ', value)
console.time('休眠')
var now = new Date().getTime();
do {
var cur = new Date().getTime();
} while (cur - now <= 5000)
console.timeEnd('休眠')
console.log('---------返回给GUI线程的数据', value * value)
postMessage('你传递过来数据的平方是:' + value * value)
}
网友评论