diff --git a/Chapter1 - iOS/1.95.md b/Chapter1 - iOS/1.95.md new file mode 100644 index 0000000..f45f59f --- /dev/null +++ b/Chapter1 - iOS/1.95.md @@ -0,0 +1,139 @@ +# 从 flutter 和前端角度出发,聊聊单线程模型下如何保证 UI 流畅性 + + + +> 文章主题是“单线程模型下如何保证 UI 的流畅性”。该话题针对的是 flutter 性能原理展开的,但是 dart 语言就是 js 的延伸,很多概念和机制都是一样的。具体不细聊。此外 js 也是单线程模型,在界面展示和 IO 等方面和 dart 类似。所以结合对比讲一下,帮助梳理和类比,更加容易掌握本文的主题,和知识的横向拓展。 +> +> 先从前端角度出发,分析下 event loop 和事件队列模型。再从 flutter 层出发聊聊 dart 侧的事件队列和同步异步任务之间的关系。 + +## 一、单线程模型的设计 + +### 1. 最基础的单线程处理简单任务 + +假设有几个任务: + +- 任务1: "姓名:" + "杭城小刘" +- 任务2: "年龄:" + "1995" + "02" + "20" +- 任务3: "大小:" + (2021 - 1995 + 1) +- 任务4: 打印任务1、2、3 的结果 + +在单线程中执行,代码可能如下: + +```c++ +//c +void mainThread () { + string name = "姓名:" + "杭城小刘"; + string birthday = "年龄:" + "1995" + "02" + "20" + int age = 2021 - 1995 + 1; + printf("个人信息为:%s, %s, 大小:%d", name.c_str(), birthday.c_str(), age); +} +``` + +线程开始执行任务,按照需求,单线程依次执行每个任务,执行完毕后线程马上退出。 + +![基础单线程模型](./../assets/2021-06-18-SingleThread1.png) + + + +### 2. 线程运行过程中来了新的任务怎么处理? + +问题1 介绍的线程模型太简单太理想了,不可能从一开始就 n 个任务就确定了,大多数情况下,会接收到新的 m 个任务。那么 section1 中的设计就无法满足该需求。 + +**要在线程运行的过程中,能够接受并执行新的任务,就需要有一个事件循环机制。**最基础的事件循环可以想到用一个循环来实现。 + +```c++ +// c++ +int getInput() { + int input = 0; + cout<< "请输入一个数"; + cin>>input; + return input; +} + +void mainThread () { + while(true) { + int input1 = getInput(); + int input2 = getInput(); + int sum = input1 + input2; + print("两数之和为:%d", sum); + } +} +``` + +相较于第一版线程设计,这一版做了以下改进: + +- 引入了**循环机制**,线程不会做完事情马上退出。 +- 引入了**事件**。线程一开始会等待用户输入,等待的时候线程处于暂停状态,当用户输入完毕,线程得到输入的信息,此时线程被激活。执行相加的操作,最终输出结果。不断的等待输入,并计算输出。 + +![](./../assets/2021-06-18-SingleThread2.png) + + + + + +### 3. 处理来自其他线程的任务 + +真实环境中的线程模块远远没有这么简单。比如浏览器环境下,线程可能正在绘制,可能会接收到1个来自用户鼠标点击的事件,1个来自网络加载 css 资源完成的事件等等。第二版线程模型虽然引入了事件循环机制,可以接受新的事件任务,但是发现没?这些任务之来自线程内部,该设计是无法接受来自其他线程的任务的。 + +![第三版线程模型](./../assets/2021-06-18-SingleThread3.png) + + + +从上图可以看出,渲染主线程会频繁接收到来自于 IO 线程的一些事件任务,当接受到的资源加载完成后的消息,则渲染线程会开始 DOM 解析;当接收到来自鼠标点击的消息,渲染主线程则会执行绑定好的鼠标点击事件脚本(js)来处理事件。 + +需要一个合理的数据结构,来存放并获取其他线程发送的消息? + +**消息队列**这个词大家都听过,在 GUI 系统中,事件队列是一个通用解决方案。 + + + +![事件队列](./../assets/2021-06-18-SingleThread4.png) + +**消息队列(事件队列)是一种合理的数据结构。要执行的任务添加到队列的尾部,需要执行的任务,从队列的头部取出。** + +有了消息队列之后,线程模型得到了升华,如下: + +![单线程模型第四版](./../assets/2021-06-18-SingleThread5.png) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Chapter1 - iOS/chapter1.md b/Chapter1 - iOS/chapter1.md index 696b239..8438e69 100644 --- a/Chapter1 - iOS/chapter1.md +++ b/Chapter1 - iOS/chapter1.md @@ -98,3 +98,4 @@ * [92、flutter 无痕埋点](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.92.md) * [93、flutter 新功能引导](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.93.md) * [94、APM-Wake Up](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.94.md) + * [95、从 flutter 和前端角度出发,聊聊单线程模型下如何保证 UI 流畅性](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.95.md) \ No newline at end of file diff --git a/SUMMARY.md b/SUMMARY.md index 67a6357..e5a1ece 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -97,6 +97,7 @@ * [92、flutter 无痕埋点](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.92.md) * [93、flutter 新功能引导](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.93.md) * [94、APM-Wake Up](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.94.md) + * [95、从 flutter 和前端角度出发,聊聊单线程模型下如何保证 UI 流畅性](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter1%20-%20iOS/1.95.md) * [Chapter2 - Web FrontEnd](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter2%20-%20Web%20FrontEnd/chapter2.md) * [1、-last-child与-last-of-type你只是会用,有研究过区别吗?](https://github.com/FantasticLBP/knowledge-kit/blob/master/Chapter2%20-%20Web%20FrontEnd/2.1.md) diff --git a/assets/2021-06-18-SingleThread1.png b/assets/2021-06-18-SingleThread1.png new file mode 100644 index 0000000..ec839af Binary files /dev/null and b/assets/2021-06-18-SingleThread1.png differ diff --git a/assets/2021-06-18-SingleThread2.png b/assets/2021-06-18-SingleThread2.png new file mode 100644 index 0000000..edcfb54 Binary files /dev/null and b/assets/2021-06-18-SingleThread2.png differ diff --git a/assets/2021-06-18-SingleThread3.png b/assets/2021-06-18-SingleThread3.png new file mode 100644 index 0000000..ffe6e46 Binary files /dev/null and b/assets/2021-06-18-SingleThread3.png differ diff --git a/assets/2021-06-18-SingleThread4.png b/assets/2021-06-18-SingleThread4.png new file mode 100644 index 0000000..a510935 Binary files /dev/null and b/assets/2021-06-18-SingleThread4.png differ diff --git a/assets/2021-06-18-SingleThread5.png b/assets/2021-06-18-SingleThread5.png new file mode 100644 index 0000000..45e110c Binary files /dev/null and b/assets/2021-06-18-SingleThread5.png differ