发布网友
发布时间:2022-04-21 13:43
共13个回答
懂视网
时间:2022-04-07 13:58
因此我们可以说JS是"单线程"式的语言,代码只能按照单一顺序进行串行执行,并在执行完成前阻塞其他代码。
【相关课程推荐:JavaScript视频教程】
JS数据结构
如上图所示为JS的几种重要数据结构:
● 栈(Stack):用于JS的函数嵌套调用,后进先出,直到栈被清空。
● 堆(Heap):用于存储大块数据的内存区域,如对象。
● 队列(Queue):用于事件循环机制,先进先出,直到队列为空。
事件循环
我们的经验告诉我们JS是可以并发执行的,比如定时任务、并发AJAX请求,那这些是怎么完成的呢?其实这些都是JS在用单线程模拟多线程完成的。
如上图所示,JS串行执行主线程任务,当遇到异步任务如定时器时,将其放入事件队列中,在主线程任务执行完毕后,再去事件队列中遍历取出队首任务进行执行,直至队列为空。
全部执行完成后,会有主监控进程,持续检测队列是否为空,如果不为空,则继续事件循环。
setTimeout定时任务
定时任务setTimeout(fn, timeout)
会先被交给浏览器的定时器模块,等延迟时间到了,再将事件放入到事件队列里,等主线程执行结束后,如果队列中没有其他任务,则会被立即处理,而如果还有没有执行完成的任务,则需要等前面的任务都执行完成才会被执行。因此setTimeout的第2个参数是最少延迟时间,而非等待时间。
当我们预期到一个操作会很繁重耗时又不想阻塞主线程的执行时,会使用立即执行任务:
setTimeout(fn, 0);
然而考虑这么一段代码会怎么执行:
setTimeout(()=>{console.log(5)},5) setTimeout(()=>{console.log(4)},4) setTimeout(()=>{console.log(3)},3) setTimeout(()=>{console.log(2)},2) setTimeout(()=>{console.log(1)},1) setTimeout(()=>{console.log(0)},0)
了解完事件队列机制,你的答案应该是0,1,2,3,4,5
,然而答案却是1,0,2,3,4,5
,这个是因为浏览器的实现机制是最小间隔为1ms。
// https://github.com/nodejs/node/blob/v8.9.4/lib/timers.js#L456 if (!(after >= 1 && after <= TIMEOUT_MAX)) after = 1; // schedule on next tick, follows browser behavior
浏览器以32位bit来存储延时,如果大于 2^32-1 ms(24.8天)
,导致溢出会立刻执行。
定时器的嵌套调用超过4层时,会导致最小间隔为4ms:
var i=0; function cb() { console.log(i, new Date().getMilliseconds()); if (i < 20) setTimeout(cb, 0); i++; } setTimeout(cb, 0);
可以看到前4层也不是标准的立刻执行,在第4层后间隔明显变大到4ms以上:
0 667 1 669 2 670 3 672 4 676 5 681 6 685Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.
为了优化后台tab的加载占用资源,浏览器对后台未激活的页面中定时器延迟限制为1s。
对追踪型脚本,如谷歌分析等,在当前页面,依然是4ms的延时限制,而后台tabs为10s。
setInterval定时任务
此时,我们会知道,setInterval会在每个定时器延时时间到了后,将一个新的事件fn放入事件队列,如果前面的任务执行太久,我们会看到连续的fn事件被执行而感觉不到时间预设间隔。
因此,我们要尽量避免使用setInterval,改用setTimeout来模拟循环定时任务。
睡眠函数
JS一直缺少休眠的语法,借助ES6新的语法,我们可以模拟这个功能,但是同样的这个方法因为借助了setTimeout也不能保证准确的睡眠延时:
function sleep(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }) } // 使用 async function test() { await sleep(3000); }
async函数是Generator函数的语法糖,提供更方便的调用和语义,上面的使用可以替换为:
function* test() { yield sleep(3000); } // 使用 var g = test(); test.next();
但是调用使用更加复杂,因此一般我们使用async函数即可。但JS时如何实现睡眠函数的呢,其实就是提供一种执行时的中间状态暂停,然后将控制权移交出去,等控制权再次交回时,从上次的断点处继续执行。因此营造了一种睡眠的假象,其实JS主线程还可以在执行其他的任务。
Generator函数调用后会返回一个内部指针,指向多个异步任务的暂停点,当调用next函数时,从上一个暂停点开始执行。
协程(coroutine)是指多个线程互相协作,完成异步任务的一种多任务异步执行的解决方案。他的运行流程:
● 协程A开始执行
● 协程A执行到一半,进入暂停,执行权转移到协程B
● 协程B在执行一段时间后,将执行权交换给A
● 协程A恢复执行
可以看到这也就是Generator函数的实现方案。
宏任务和微任务
一个JS的任务可以定义为:在标准执行机制中,即将被调度执行的所有代码块。
我们上面介绍了JS如何使用单线程完成异步多任务调用,但我们知道JS的异步任务分很多种,如setTimeout定时器、Promise异步回调任务等,它们的执行优先级又一样吗?
答案是不。JS在异步任务上有更细致的划分,它分为两种:
宏任务(macrotask)包含:
● 执行的一段JS代码块,如控制台、script元素中包含的内容。
● 事件绑定的回调函数,如点击事件。
● 定时器创建的回调,如setTimeout和setInterval。
微任务(microtask)包含:
● Promise对象的thenable函数。
● Nodejs中的process.nextTick函数。
● JS专用的queueMicrotask()函数。
宏任务和微任务都有自身的事件循环机制,也拥有独立的事件队列(Event Queue),都会按照队列的顺序依次执行。但宏任务和微任务主要有两点区别:
1、宏任务执行完成,在控制权交还给主线程执行其他宏任务之前,会将微任务队列中的所有任务执行完成。
2、微任务创建的新的微任务,会在下一个宏任务执行之前被继续遍历执行,直到微任务队列为空。
浏览器的进程和线程
浏览器是多进程式的,每个页面和插件都是一个独立的进程,这样可以保证单页面崩溃或者插件崩溃不会影响到其他页面和浏览器整体的稳定运行。
它主要包括:
1、主进程:负责浏览器界面显示和管理,如前进、后退,新增、关闭,网络资源的下载和管理。
2、第三方插件进程:当启用插件时,每个插件独立一个进程。
3、GPU进程:全局唯一,用于3D图形绘制。
4、Renderer渲染进程:每个页面一个进程,互不影响,执行事件处理、脚本执行、页面渲染。
浏览器的单个页面就是一个进程,指的就是Renderer进程,而进程中又包含有多个线程用于处理不同的任务,主要包括:
1、GUI渲染线程:负责HTML和CSS的构建成DOM树,渲染页面,比如重绘。
2、JS引擎线程:JS内核,如Chrome的V8引擎,负责解析执行JS代码。
3、事件触发线程:如点击等事件存在绑定回调时,触发后会被放入宏任务事件队列。
4、定时触发器线程:setTimeout和setInterval的定时计数器,在时间到达后放入宏任务事件队列。
5、异步HTTP请求线程:XMLHTTPRequest请求后新开一个线程,等待状态改变后,如果存在回调函数,就将其放入宏任务队列。
需要注意的是,GUI渲染进程和JS引擎进程互斥,两者只会同时执行一个。主要的原因是为了节流,因为JS的执行会可能多次改变页面,页面的改变也会多次调用JS,如resize。因此浏览器采用的策略是交替执行,每个宏任务执行完成后,执行GUI渲染,然后执行下一个宏任务。
因为JS只有一个引擎线程,同时和GUI渲染线程互斥,因此在繁重任务执行时会导致页面卡住,所以在HTML5中支持了Webworker,它用于向浏览器申请一个新的子线程执行任务,并通过postMessage API来和worker线程通信。所以我们在繁重任务执行时,可以选择新开一个Worker线程来执行,并在执行结束后通信给主线程,这样不会影响页面的正常渲染和使用。
总结
1、JS是单线程、阻塞式执行语言。
2、JS通过事件循环机制来完成异步任务并发执行。
3、JS将任务细分为宏任务和微任务来提供执行优先级。
4、浏览器单页面为一个进程,包含的JS引擎线程和GUI渲染线程互斥,可以通过新开Web Worker线程来完成繁重的计算任务。
最后给大家出一个考题,可以猜下执行的输出结果来验证学习成果:
function sleep(ms) { console.log('before first microtask init'); new Promise(resolve => { console.log('first microtask'); resolve() }) .then(() => {console.log('finish first microtask')}); console.log('after first microtask init'); return new Promise(resolve => { console.log('second microtask'); setTimeout(resolve, ms); }); } setTimeout(async () => { console.log('start task'); await sleep(3000); console.log('end task'); }, 0); setTimeout(() => console.log('add event'), 0); console.log('main thread');
输出为:
main thread start task before first microtask init first microtask after first microtask init second microtask finish first microtask add event end task
本文来自 js教程 栏目,欢迎学习!
热心网友
时间:2022-04-07 11:06
根据个人实际的经历,结合多种书籍,特别整理出了下面的java学习路线:
一、Java SE部分
1、java基础:基础语法;面向对象(重点);集合框架(重点);常见类库API;
2、java界面编程:AWT;事件机制;Swing;
3、java高级知识:Annotation;IO和NIO、AIO;多线程、线程池;阻塞、非阻塞、异步网络通信;反射、动态代理;
二、JDBC编程
4、SQL基础:基础SQL语句;基本查询;多表查询;子查询;结果集的交、并、差运算;
5、JDBC基础:常见数据库用法;JDBC操作常见数据库;RowSet与离线结果集;数据库连接池;事务管理、批处理;
6、JDBC进阶:存储过程、函数;触发器;理解JCBC的不足;掌握ORM工具优势和设计;
三、DHTML编程
7、HTML基础:基本HTML标签;常见表单标签;DIV+CSS布局;
8、JavaScript知识:javascript基本语法;javascript基本对象特征;Json语法;深刻理解javascript的动态特征;
9、Dom和事件机制:DOM操作、编程;常见浏览器事件机制;掌握用户交互技巧;
四、XML编程
10、XML基础:XML基础规则;DTD和SCheme;XML和样式单;
11、XML进阶:DOM、SAX和JAXP;dom4j、JDOM等工具;XQuery和XQJ;基于XML的数据交换;
12、Web Service:JAX_WS2、SAAJ规范;WSDL和SOAP协议;CXF框架、*;CXF整合Spring;
五、Java Web编程
13、Web编程基础:Tomcat服务器;Jsp语法、EL、内置对象;Servlet API;Servlet 3.0注解;Listener和Filter;
14、Web编程进阶:自定义标签库;MVC和DAO、Servlet、标签的作用;JSTL、DisplayTag等常见标签库用法;
15、Web编程原理:请求/响应、架构;Http协议;深刻理解Jsp运行原理;掌握Web容器底层的线程池、socket通信、调用Servlet的命令模式;
六、Ajax编程:
16、Ajax编程:XML HttpRequest和异步请求;发送请求和处理响应;常见Ajax库(Prototype、Jquery、ExtJs、DWR)用法;结合Http协议、异步请求深入研究ajax库的设计;
七、Android开发
17、Android基础:Android开发调试环境;Android应用结构;界面组件与界面编程;资源管理;四大组件;
18、Android中级:文件IO和SQLite;图形、图像与动画;音频、视频的录制与播放;传感器编程;GPS应用;
19、Android高级:网络编程与Web Service;OpenGL_ES 3D开发;整合Google服务;使用NDK开发;java和c相互调试;
八、轻量级Java EE
17、Struts2:MVC与struts体系;Action和Result;国际化和标签库;文件上传、下载;类型转换和输入检验;*与插件开发;
18、Hibernate:ORM与持久化映射;关系映射、继承映射;延迟加载、性能调优;HQL查询、条件查询、SQL查询;二级缓存和查询缓存;
19、Spring:IoC与Bean配置、管理;Bean生命周期;SP、EL;AOP与事务权限控制;S2SH整合开发;Spring整合Jpa;
九、经典Java EE
20、JSF<选学>:MVC与JSF设计理念;托管Bean与导航模型;JSF流程与事件机制;JSF标签库;类型转换与输入检验;
21、EJB及相关技术:JNPI与RMI;会话Bean及其生命周期;IoC与EJB*;JMS与MDB;会话Bean与Web Service;
22、JPA:ORM框架与JPA规范;JPA注解与常用API;JTA事务与事务管理;JPQL查询;EJB、JPA整合;
十、Java 拓展、进阶:
23、Java EE实践与架构:Ant+Ivy或Maven;SVN、CVS;深刻理解10种以上设计模式;掌握各种Java EE架构及各自优势;
24、Workflow:Workflow规范及功能;JBPM等workflow框架;多次重构、反复思考;大型项目经验;
25、Java EE进阶:掌握各MVC框架运行原理、能开发类似框架;掌握Spring、HiveMind、AspectJ等框架原理、能开发类似工具;掌握Hibernate、iBatis等框架原理,能开发类似工具;深入研究EJB机制、大致了解应用服务器的实现;如果想学编程的可以我这看看哦。如果想系统的学习编程的可以来我这看看哦
希望对您有所帮助!~
热心网友
时间:2022-04-07 12:24
热心网友
时间:2022-04-07 13:59
学习java不知道用什么方法?记住了一定要多看视频,视频内容丰富使学习不那么枯燥,推荐b站上的高淇老师讲的java还不错,可以了解了解,多看多动手
下面是2020年最新的Java学习路线图整理分享给大家!
学习是一个枯燥且无聊的过程,希望我整理的资料能够帮助大家!
共同走向年薪百万;
Java编程语言占比:
据官方数据统计,在全球编程语言工程师的数量上,Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程,因此其程序员的数量最多。而在以Java编程为核心的开发领域中,企业级程序员的需求量10年来一直居于首位!
目前各个大厂的的招聘,Java也是稳居首位!
那么系统的学习Java线路图,展示分享给大家:
一、JavaSE基础阶段
面向对象编程(基础)
面向对象编程(进阶)
异常机制
Java常用类
数据结构和算法
集合(容器)
IO流
多线程
网络编程
集合提升训练
多线程提升训练
二、数据库阶段
MySQL基础
MySQL 查询语句
数据库对象
JDBC
反射和注解
数据库建模和UML建模
设计模式
三、WEB前端
JavaScript
jQuery
BootStrap
Vue
四、JavaEE阶段 (核心阶段)
HTTP/Tomcat
MVC 架构
Servlet
JSP
EL+JSTL+过滤器+*
Ajax和JSON
分页和文件上传/下载
五、JavaEE阶段(高级框架)
Spring 5.2.2
SpringMVC 5.2.2
RBAC
EasyUI 1.7.0
支付/短信验证
六、框架强化
Linux - CentOS 8
Maven
Logback
Quartz
Spring Boot 2.2.2
Shiro
Swagger
Git/GitEE
MyBatis
七、分布式架构
Zookeeper
RPC
Dubbo
Redis
Solr
RabbitMQ
FastDFS
Nginx
Spring Security
Spring Session
MyBatis Generator
Mycat
八、微服务阶段
ElasticSearch
MongoDB
Spring Cloud Netflix Eureka
Spring Cloud Netflix Ribbon
Spring Cloud OpenFeign
Spring Cloud Netflix Hystrix
Spring Cloud Config
Spring Cloud Gateway
Docker
K8S
LCN
希望我的回答可以帮到你,记住一定多看视频,多动手敲代码。
热心网友
时间:2022-04-07 15:50
Java全新学习路线图如下:
热心网友
时间:2022-04-07 17:58
热心网友
时间:2022-04-07 20:23
Java基础到项目实战:(建议保存格式bpm)
热心网友
时间:2022-04-07 23:04
热心网友
时间:2022-04-08 02:02
java学习路线图
java学习路线
第1阶段Java核心技术
第2阶段数据库关键技术
第3阶段Web开发与实战应用
第4阶段经典&流行框架
第5阶段Java高级&前沿技术
第6阶段企业接轨项目以在线教育项目为例
第7阶段大数据技术
热心网友
时间:2022-04-08 05:17
Java前景是很不错的,像Java这样的专业还是一线城市比较好,师资力量跟得上、就业的薪资也是可观的,Java学习路线有8个阶段,
0基础学习Java是没有问题的,关键是找到靠谱的Java培训机构,你可以深度了解机构的口碑情况,问问周围知道这家机构的人,除了口碑再了解机构的以下几方面:
1. 师资力量雄厚
要想有1+1>2的实际效果,很关键的一点是师资队伍,你接下来无论是找个工作还是工作中出任哪些的人物角色,都越来越爱你本身的技术专业java技术性,也许的技术专业java技术性则绝大多数来自你的技术专业java教师,一个好的java培训机构必须具备雄厚的师资力量。
2. 就业保障完善
实现1+1>2效果的关键在于能够为你提供良好的发展平台,即能够为你提供良好的就业保障,让学员能够学到实在实在的知识,并向java学员提供一对一的就业指导,确保学员找到自己的心理工作。
3. 学费性价比高
一个好的Java培训机构肯定能给你带来1+1>2的效果,如果你在一个由专业的Java教师领导并由Java培训机构自己提供的平台上工作,你将获得比以往更多的投资。
希望你早日学有所成。
热心网友
时间:2022-04-08 08:48
热心网友
时间:2022-04-08 12:36
希望对你有所帮助!
热心网友
时间:2022-04-08 16:41