第三梯队思想
第三梯队思想
第三梯队思想,是程序执行流程的高层构建块,能够用来构建灵活而强大的指令流程。
管道
管道是类 Unix 系统的经典发明。管道将左边程序的输出传给右边程序的输入,可以轻易将连接的多个实用程序组成一条流水线,实现强大而多样化的功能(小程序、微功能)。
比如如下命令:在当前目录及子目录下的所有 .java 文件中查找匹配模式 pattern 的字符串,显示文件名,行号及匹配的行内容。
find . -name '*.java' | xargs awk ' $0 ~ /pattern/ { printf "%s : Line %s :\n%s \n" , FILENAME, FNR, $0 } ' | sed 's/^[[:space:]]\{1,\}/ /'
并发
并发是同一个执行单元在一段时间内交替做多件事情。
比如一个人一边烧水,一遍看电视,一遍督促孩子做作业。看上去就像是在同一时间段内同时做了多件事情。由于某一项需要等待,往往在多项任务之间不断切换(保留现场和恢复现场)。切换会耗费一定的时间。
并发是利用多核的性能提升手段。事实上,并发也是世界运行的本质。这个世界正是由不计其数的人并发地去进行自己的活动所构建起来的。
并行
并行是多个互相独立的执行单元在同一段时间相互独立地做不同事情。
比如一个公司里,产品在理需求,研发在做技术调研,两个人都是朝同一目标前进,但做着不同的事情。
并行是并发的一种更严格的形式。
批量
涉及网络传输时,单个单个去获取数据和处理数据往往会比较慢,因为传输的次数增多,需要反复建立和销毁连接,会耗费不必要的连接建立时间和传输时间,尤其是连接建立成本、传输成本与处理成本相当甚至更大的情形。
比如传输一次需要 10s, 处理一个需要 5s。如果单个处理,那么处理 10 个需要 (10+5)10 = 150s;而如果一次批量获取10个,然后批量处理,则只需要 10 + 510 = 60s。 中间 90s 的传输成本都是不必要的。因此大量数据的获取和处理,往往是批量方式处理的。
比如运货,通常是一整箱一整箱地运送,而不是一个个的运送。
批量是提升大量数据处理的效率的常用手段。
异步
异步最初是为了解决响应的体验问题。在提交后台任务执行的同时,给前端先返回一个消息,让用户能够有所感知,而不是百无聊赖的等待。异步,多用于解耦后台耗时任务与前台展示。
多路 IO 复用,是异步方式解决高并发问题的技术基础。
回调
回调有点类似于埋点。指定做完一件事之后,要去处理一段特定逻辑,而这段特定逻辑可能是不同的。这段特定逻辑就称为回调逻辑。
回调能够让函数的功能更加灵活,是函数式编程的重要特征之一。回调的函数参数通常是函数指针。
延迟
亦称惰性加载。仅在必要时才去加载、访问和计算。
通常用于创建需要耗费资源较大的对象,或者将访问和计算延迟到必要的时候才去进行,以减少不必要的消耗。
比如说,举办一次会议,仅在会前一天或几个小时,才有必要在会场去”铺设“饮用矿泉水。因为如果提前去铺设,万一会议取消了,或者转换场地了,那么这些努力(连带时间和精力)就都白费了;比如说颁奖,只有在需要颁奖的时候,才让获奖人上台领奖,而不是从一开始就在台前等着。
延迟加载的常见使用场景:
- 大图片延迟加载。浏览网站时,往往会先展示图片的缩略图,点击之后才会展示原图,这即是一种延迟加载策略。
- Stream 流计算。 从 Stream 流读取数据,可以进行 filter, map,flatmap 等各种操作,但只有在 collect 的时候才进行计算。
- 初始化大对象。 对于创建开销高昂的对象,仅在需要的时候才去创建。
定时
定时是在指定的时间周期性地做一件事。
软件系统中充满了各种定时任务。比如闹钟就是一个定时任务。
通知
与定时的指定时间不同,通知,是在所关注的事情发生变化时,发送消息通知,以便做相应处理。
比如订阅了一个公众号,公众号在发布文章时,就会给你推送一个消息。
通知往往是基于事件驱动机制或订阅推送机制来实现的。
阻塞
我们自然希望程序能够时时刻刻流畅无阻地永远运行下去,但人类的思维能力是有限的。面对现实的复杂多变,很难做到如此完美。
阻塞,也是一种重要的编程思想。阻塞用于两种情形:
- 适当阻塞,可以消减大规模程序的快速运转状况下的时间差(这种时间差是人很难消除和预料的)导致的 BUG,让程序行为容易推断;
- 程序在大流量的侵袭下,适当阻塞,能够让程序免于瞬间崩溃,有效利用系统资源。
当然,程序阻塞也可以实现让客户持续付费
排队机制,也是一种阻塞实现。当数据量超过系统能力承载范围时,让数据先入队等待,待系统处理有余力时再出队处理。“生产者-消费者”模式就是一种经典的阻塞并发模式。
阻塞有利有弊。可控地阻塞时,可以让系统有节奏地处理; 重度阻塞时,就可能会导致系统运行进一步恶化,最终导致崩溃。不可不防。