多线程语言

像java、python等 它们都是仅支持同步语言,像读取文件、网络请求这种任务 花费时间很长,它们只能长时间等着。

遇到其他紧急任务,Java 可以再开一个线程去处理。

多线程语言的好处是,在同一时间让 cpu 处理多个事情。

充分的利用cpu多核多线程的资源优势。

程序也会执行的更快!

支持多线程的语言有特别多,比如java、python 等

class RunnableDemo implements Runnable {
private Thread t;
private final String threadName;
RunnableDemo( String name) {
threadName = name;
System.out.println("创建 " + threadName );
} public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("运行 " + threadName );
} public void start () {
System.out.println("启动 " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
} public class Main {
// 默认第1个主线程
public static void main(String[] args) {
System.out.println("主线程运行" );
new RunnableDemo( "线程2").start(); // 开启第2个线程(虽然等待3s,但是下边代码会同事执行 不会阻断)
new RunnableDemo( "线程3").start(); // 开启第3个线程
}
}

单线程语言

像类似于 js等语言,由于单线程限制,则不能同时调用cpu的多线程 跑任务,它只能一个时间点只能做一件事情,遇到耗时的任务 这种长时间的空闲等待是不可接受的。

所以js便采取了以下的“异步任务回调通知”模式 来达到类似的效果(关于js异步相关的知识 下边单独讲)

console.log("主程序1结束");
setTimeout(() => {
console.log("异步程序2");
}, 3000); // 虽然需要耗时3s 单并不会阻塞后续代码执行(这里类似于开线程的效果)
console.log('主程序1结束');

事件循环

事件循环是JavaScript实现异步的一种方法,也是JavaScript的执行机制

JS 本身不实现事件循环机制,这是由它的宿主实现的,浏览器中的事件循环主要是由浏览器来实现,而在 NodeJS 中也有自己的事件循环实现。

当一段JS代码执行的时候,首先它是从磁盘被加载到内存(划分一片空间上下文,也叫做执行栈),然后cpu 去执行,

1· JS 引擎会从上到下、从左到右的执行完成所有的同步任务,期间碰到异步任务的时候放到任务队列中。

2. 所有的同步任务执行完毕,主线程会去看看任务队列是否有任务,若有任务则将任务推到主线程执行

3. 执行结束,会再次去看任务队列是否有任务 以此类推 循环往复 每一次循环就是一个事件周期或称为一次 tick。

在处理任务队列中的任务的时候 还有一个点

  1. 若有微任务,则优先将本轮所有微任务的执行完成,全部结束后 再执行本轮的宏任务

浏览器端的异步实现(事件循环)

以 Chrome 为例,浏览器不仅有多个线程,还有多个进程,如渲染进程、GPU 进程和插件进程等、甚至每个 tab 标签页都是一个独立的渲染进程(所以一个 tab 异常崩溃后,其他 tab 基本不会被影响)。

作为前端开发者,主要重点关注其渲染进程,渲染进程下包含了 JS 引擎线程、HTTP 请求线程和定时器线程等,这些线程为 JS 在浏览器中完成异步任务提供了基础。

JS 是单线程的,也就是同一个时刻只能做一件事情,那么思考:为什么浏览器可以同时执行异步任务呢?

可千万不要搞混了 浏览器本身是多线程的,单线程的只是你的js代码语言本身,

当 JS 需要执行异步任务时,浏览器会另外启动一个线程去执行该任务。

也就是说,“JS 是单线程的”指的是执行 JS 代码的线程只有一个,是浏览器提供的 JS 引擎线程(主线程)。

浏览器中还有定时器线程和 HTTP 请求线程等,这些线程主要不是来跑 JS 代码的。

比如主线程中需要发一个 AJAX 请求,就把这个任务交给另一个浏览器线程(HTTP 请求线程)去真正发送请求,待请求回来了,再将 callback 里需要执行的 JS 回调交给 JS 引擎线程去执行。

即浏览器才是真正执行发送请求这个任务的角色,而 JS 只是负责执行最后的回调处理。

所以这里的异步不是 JS 自身实现的,其实是浏览器为其提供的能力。

webworker

比如说 下边一段代码 非常卡 因为运算量大,这就导致弹窗半天才出来 要怎么解决

let sum = 0;
for (let i = 0; i < 200000; i++) {
for (let i = 0; i < 10000; i++) {
sum += Math.random();
}
}
alert("哈哈");

有很多人可能会这样想

const getSum = () => {
return new Promise((reslove) => {
let sum = 0;
for (let i = 0; i < 20000; i++) {
for (let i = 0; i < 10000; i++) {
sum += Math.random();
}
}
reslove(sum)
});
};
getSum().then(res=>{
console.log(res);
})
alert("哈哈");

事实上 这样没用

Promise 是用来管理异步编程的,它本身不是异步的 ,promise是同步代码

走的依然是所有js同步代码都公用的JS 引擎线程

所以就会阻塞下边的js代码。

那就找一个 可以触发浏览器单独线程的代码 使其在另一个线程运行就行了,这样就可以了

setTimeout(() => {
let sum = 0;
for (let i = 0; i < 20000; i++) {
for (let i = 0; i < 10000; i++) {
sum += Math.random();
}
}
});
alert("哈哈");

当然最后 还是搬出我们web worker,他可以不借助任何浏览器提供的线程方案,而是自己单独开一个线程

你每次new Worker都会开启一个新线程

// 主线程 index.js
const worker = new Worker("work.js");
// 线程之间通过postMessage进行通信
worker.postMessage(0); // 向子线程发消息
// 监听线程之间message事件
worker.onmessage = function (e) { // 接受子线程的消息
// 关闭线程
worker.terminate();
// 获取计算结束的时间
console.log("计算结果:", e.data);
console.log(`代码执行了 ${e.timeStamp} 毫秒`);
};
alert("哈哈"); // 子线程 work.js
this.addEventListener("message", (e) => { // 接受主线程的消息
let sum = e;
for (let i = 0; i < 2000; i++) {
for (let i = 0; i < 100; i++) {
sum += Math.random();
}
}
postMessage(sum); // 向主线程发消息
});

web worker总结

这里是web worker的官方文档

WebWorker是HTML5提供的一种浏览器内置的多线程解决方案,就是为js创造多线程的环境。

允许主线程创建webwork线程,将未处理的一些任务分给后者

运行.在js主线程运行的同时,work线程在后台运行,两者互不打扰

等到webwork线程的任务结束后,把结果返回给主线程

web worker的注意点

(1) 同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(2) DOM限制:Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
(3) 通信联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成
(4) 脚本限制:Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
(5) 文件限制: Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

postMessage 传递消息的时候 需要传入的是字符串或可以序列化的对象,否则会出现错误。

小结

虽然js语言本身不能多线程,但是浏览器背后可以做,你的每一个异步,对应就是它在后台帮你多线程做任务。

即便这样 最新的webworker 还是给了你开启线程任务的能力!

JS是门单线程语言的更多相关文章

  1. 探秘JS的异步单线程

    对于通常的developer(特别是那些具备并行计算/多线程背景知识的developer)来讲,js的异步处理着实称得上诡异.而这个诡异从结果上讲,是由js的“单线程”这个特性所导致的. 我曾尝试用“ ...

  2. js为什么是单线程的?10分钟了解js引擎的执行机制

    深入理解JS引擎的执行机制 1.JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.说说setT ...

  3. JS(异步与单线程)

    JS(异步与单线程) 题目1.同步和异步的区别是什么,试举例(例子见知识点) 区别: 1.同步会阻塞代码执行,而异步不会 2.alert 是同步,setTimeout 是异步 题目2.关于 setTi ...

  4. 对QT的理解——能在公司里不做Java,不做很偏门的产品,不使用偏门的语言,还有钱挣,要有感恩的心

    我的理解: QT做应用软件可以很强大,界面足够漂亮(最有意思的是QSS,让我刮目相看),应该是足够了.同时QT也提供了源码,不过超级复杂,难以理解,所以还是无法深入底层.另外它提供了一个额外的好处,就 ...

  5. 基于JS的高级脚本语言 Sara

    Sara-基于JS的高级脚本语言 欢迎使用Sara,Sara是一款基于JavaScript的全新的高级脚本语言! Sara不像我们工作室上一款编程语言作品-Ginit一样,他属于更高级的语言 Sara ...

  6. WASM 成为 HTML、CSS 与 JS 之后的第 4 门 Web 语言

    大家都知道,万维网联盟 W3C 认证的 Web 语言有 HTML.CSS 与 JavaScript,而近日联盟正式宣布 WebAssembly 核心规范(WebAssembly Core Specif ...

  7. JS有趣的单线程

    一.JS的执行特点    源于单线程的特性, JS在一段时间内只能执行一部分代码, 那么, 当有多块代码需要执行时, 就需要排队等候了.   二.单线程与异步事件 (1) 什么是异步事件?     异 ...

  8. JS为什么是单线程的?

    JavaScript语言最大的特点就是单线程.它是浏览器的脚本语言.在同一时间只能做一件事.用于操作DOM.如果JS是多线程的,当我在给一个DOM添加内容时,又删除了这个DOM,那么JS该怎么做. 关 ...

  9. [Js]滑动门效果

    描述:鼠标移动到一副图片上,会显示该副图片的全貌,而其他图片会显示概貌 一.没有动画效果的运动 思路: 1.定好每张图片的初始位置(第一张完全显示,234只露出一部分) 2.计算每道门的移动距离(即未 ...

  10. js 滑动门的实现

    原理:滑动门,这里以图片进行实例,首先设定主盒子div的宽度和高度设定,并进行图片初始化位置的设定,然后将图片绑定事件,并设定要达到的效果 html代码: <!DOCTYPE html> ...

随机推荐

  1. ipconfig出现媒体状态为媒体已断开连接问题

    1.可能是因为路由器或者是交换机没有DHCP功能,需要手动的给电脑配置IP和掩码

  2. Robot Framework原生库的编辑与应用

    RF有一些操作指令不存在,需要自己添加方法,比如selenium里有click_and_hold指令(鼠标保持点击状态)而RF内没有.所以需要在库文件里加入这个方法 C:\Python27\Lib\s ...

  3. Python3多线程

    一.进程和线程 进程:是程序的一次执行,每个进程都有自己的地址空间.内存.数据栈及其他记录运行轨迹的辅助数据. 线程:所有的线程都运行在同一个进程当中,共享相同的运行环境.线程有开始.顺序执行和结束三 ...

  4. GoView:Start14.6k,上车啦上车啦,Vue3低代码平台GoView,零代码+全栈框架

    GoView:Start14.6k,上车啦上车啦,Vue3低代码平台GoView,零代码+全栈框架 项目介绍 GoView 是一个Vue3搭建的低代码数据可视化开发平台,将图表或页面元素封装为基础组件 ...

  5. 通过adb访问SQLite数据库

    根据<第一行代码>第二版进入到数据库的文件夹,但是如果照书本直接cd data/data/包名/databases 的话是会报错的,错误信息如下 cd: /data/data/包名 /da ...

  6. Java8 新特性-Lambda表达式

    目录 1.Lambda表达式介绍 2.Lambda表达式语法细讲 3. Lambda表达式语法精简 4. Lambda方法引用 5. 综合实例 6. @FunctionalInterface注解 7. ...

  7. 重载(Overloading)与重写(Override)的区别?

    重载(Overloading)与重写(Override)的区别? No. 区别 重载 重写 1 英文单词 Overloading Override 2 发生范围 发生在一个类里面 发生在继承关系中 3 ...

  8. json格式转为List集合

    一.JSON格式 {"code":"200","msg":"success","data":[&qu ...

  9. 使用libdivide加速整数除法运算

    在x86和ARM平台上,整数除法是相对较慢的操作.不巧的是除法在日常开发中使用频率并不低,而且还有一些其他常用的运算依赖于除法操作,比如取模.因此频繁的除法操作很容易成为程序的性能瓶颈,尤其是在一些数 ...

  10. POWERBI_创建工作区应用_协同办公能力 up up up

    在powerbi中,我们往往会创建很多不同模型的报表,他们分别独立,但是在业务决策过程中,我们需要跨报表查看数据,反复切换报表,低效且忙乱 这个时候,合并展示报表是至关重要的 今天就一起学习一下,如何 ...