不管在哪门开发语言中,多线程都是绕不过去的开发方式。多线程本身也不是开发语言的一部分,只是开发语言会对多线程进行语言级别的包装。
多线程属于计算机原理的一部分。每个应用都需要操作系统分配一个进程后才能在进程中执行,为了实现并发效果,才有了多进程方案。而进程切换开销太大,这才有了多线程方案。乃至于多线程也是有不小的内存和 CPU 开销,后面的协程才开始起家。
但是协程已经不属于计算机的范畴,协程是单线程的,需要语言级别实现的。有些语言并没有实现协程,也只能使用多线程的方案对 CPU 资源进行深一步的榨干。

像 iOS 开发里面,每个应用都是独立的沙盒,官方并没有提供多进程的方案 (操作系统级别肯定要支持),也没有提供协程方案,如果想更有效的利用 CPU 资源,只能从多线程上面入手。

iOS 里面多线程虽然理解起来有点绕,尤其任务和队列嵌套的时候。但只要多使用几次并加以过程分析,多线程的使用也就能很好的过关了。因为 GCD 本身已经对多线程有了非常棒对封装,只要不自己作死,串型队列和同步任务一起处理的时候小心一些,就不会出现队列等待导致死锁。即使死锁了,像这样的系统中断性问题,也很容易排查和处理。

那多线程,难点在哪里呢?显然不是 Api 级别的多线程接口调用。

运行时 (Runtime) 本身是一个非常普通的概念,每个编程语言都会有运行时,非 iOS Objective-C 特有。
概念上理解,
运行时,就是程序执行的过程
,每个编程语言,只有运行后执行特定的任务才有价值,所以每个编程语言,都有运行时。
而 Objective-C 的 Runtime 显然不仅仅是程序执行过程这么简单,它一举将基于面向过程的语言 C 而实现的面向对象的语言 Objective-C 变成了动态语言
为什么 Objective-C 的 Runtime 有些难理解,因为运行时从概念上理解非常简单,但是 Java、Python、C 它们的运行时都是不一样的,运行时期间可以做很多事情,所以运行时理解起来还是比较抽象和高阶。
如果把 Runtime 改名为 OCDR(Objective-C Dynamic Resolution,即 Objective-C 动态决议),剥离运行时和运行时库的概念,那么很多人都会轻松掌握 Objective-C Runtime 的核心。而 Objective-C Runtime 本质上的确就在践行动态决议这么一个过程。

2020.01.28,大年初四,疫情已经四处开花了。那天,我坐在出租屋里和孩子玩。我突然想到,2019 年的年度总结我已经写出来了,但是 2020 年都过去两个月了,可是 Flag 呢?好像是丢了。
像我这样到人,除了抽烟一直没能戒掉,做其他事还是计划感挺强的。我觉得 2020 年,应该立个 Flag。

很多人都喜欢打比方来阐述一件事情,比如说 “xxx 就是一个例子”、“有 xxx 一个例子”、“我和你打一个这样的比方 xxx”,比方说完之后,就开始阐述自己的观点。

打比方是一个久经沙场,百试不爽的论证妙计。怎么让对方跟着你的节奏走?当然是打个比方。比方一般都比较有趣,尤其带有故事性,很容易带节奏。而观点但凡和比方有一点相合,那比方就是绝佳的药引子。

但事实是:观点可能是错的,比方可能是不存在的,观点和比方的相合度可能是 1% 的交集,但观点却被采纳了!

很多互联网服务都会开通 IM 功能,如好友通讯,用户反馈,在线推送等。在微信未盛行,QQ 大行其道的年代,IM 还属于高深技术,目前已经进入寻常百姓家了。
其实 IM 本身整个技术流程从终端角度来看不是一个难以理解的问题。但因为诸多人对网络协议不了解,所以认为 IM 难以入门。

首先要说 IM 是一个什么样的形态,它和 HTTP/S 有什么不同。
HTTP 解决了端到端通讯的问题,在互联网大放异彩的原因是浏览器的盛行。冲浪需要网络获取服务端资源,HTTP 可以使得终端发起网络请求服务端返回资源结果实现资源互通。
我们的感知里面,终端发起网络请求,服务端回复网络请求,HTTP 使命就完成了。所以很多人对于 HTTP 的认知是:一次性通讯,每次需要获取信息都要重新发起请求。
其实有这样的认知是完全正确的,因为 HTTP 的确就是这样设计的。这里要着重说到设计这个词,因为 HTTP 就是为了完成一次性通讯这么一个任务。而像 HTTP 这样的应用层协议还有非常多,比如 FTP、RTMP 等等。他们都是为了完成特定任务而实现的协议。所有应用层协议都是被设计过的,为了完成特定的使命。

如果不是 2019-nCoV,我都不会有这个想法。我一直觉得自己还年轻,如果不是车祸等天灾,怎么也轮不到我来思考死亡。但是风水转动的就是如此的快,每个大陆人都有感染的风险,感染后会有死亡的可能。
当然如果自己不作,做好防护工作,那肯定是相对安全的,当然这也是概率问题,概率和幸福指数直接相关,可惜我还不能理解概率。

这次疫情距离很多人都很近,尤其是一二线城市生活的人。我相信自己不会太作到去碰触病毒,但是我也认识到,不管天灾人祸还是自身疾病,不同年龄段的人都有可能突然离开。或许因为车祸,或许因为疾病,人类在未知和概率面前,还是太渺小。
而如果我的人生,突然只剩下 8 小时,我会做些什么?

雪粉已经是大众熟知的美食,不仅国内家家户户必备,国外也是一抢而空。但很少有人知道雪粉的制作过程,而我的家乡,却是雪粉生产大本营。我对雪粉,一来情有独钟,它对家乡的经济发展有巨大的推动力,二来感到惋惜,除了我的家乡,很少有人知道雪粉的制作流程,国外也只能依靠进口才能品尝一二。

雪粉这样的美食原材料,本应该被更多人了解。我网上查阅了很多资料,都没有详细介绍。我想,我可以把雪粉的制作过程写出来,也算给了雪粉一个互联网的名份。

谈数据结构的时候,到底在谈论什么?本质上就是谈论两个东西,分别是 ** 数组 (Array) 链表 (Linked List)**。

数据物理结构和数据逻辑结构

数组和链表,是数据存储计算机的物理结构,所以叫做数据物理结构。而队列、散列表、堆、树、图等,已经超出了物理结构,是方便我们使用的应用层结构,根据数据的 1-1、1-n、n-1、n-n 逻辑关系,引申出了数据逻辑结构。分别为线性结构和非线性结构,相见下图:

参加工作后的这几年,评价哪一年比较平庸或许都不好,毕竟都是自己亲身经历过的时光,每一年都是像孩子一样善待过,不忍心批评。

但就像每人心里都有一个钟意的水杯,我还是很想投 2019 一票,因为这一年,我的确有不少变化。

这一年,我在技能成长、认知提升、工作、家庭生活、业余生活上都有很大变化。优秀肯定无从谈起,人一定要对自己有自知,但我一定是在向前走的,这让我很高兴。

技能成长

先从 2019 年的技能成长说起,因为它给我的温差最大,有时候我激动万分,有时候也在半夜垂头懊恼。

在 Swift 中,struct(值类型)和 class(引用类型)的区别,不仅仅在于对象复制时候表现出来的差异,也不仅仅是构造器和继承的异同,本质上却是数据抽象层级的高低。
如果不能把值传参、地址传参和引用传参与类对象联系起来,也无法理解不同传参下对象的使用和 struct、class 的应用场景。

因为 struct 和 class 表现出来的是语法层面的差异,而项目使用中体现的是语义层级的差异。比如,Objective-C 里面的 NSString,它是引用类型,但是我们却在使用它的值语义。

1
2
3
4
5
6
7
NSMutableString *oldname = @"hello".mutableCopy;
NSMutableString *newname = oldname;
newname = @"word".mutableCopy;
NSLog(@"\n oldName:%@ \n newName:%@", oldname, newname);

> oldName:hello
> newName:word

我们使用了引用类型的 NSMutableString,但是 newname 并没有引用复制 oldname,仅仅是指针地址复制了 oldname。这样导致了 newname 并不是 oldname 的别名 (alias)。
如果 newname 是 oldname 的别名,那么对 newname 的所有 all 操作,都会同步到 oldname。
这里,newname 如果改变了对象数据是可以同步到 oldname,但是却不能改变 oldname 变量的值(oldname 的存储值,即 “hello” 的指针地址)。
所以,这里的 NSMutableString 虽然是引用类型,却具有值语义。

因为编程语言概念上的模糊,下面首先介绍 struct 和值类型的关系。
然后重点说明值类型和引用类型的区别,这是重点,直接解释了 struct 和 class 的根本区别。
最后加一点小彩蛋,介绍 Swift 里面 struct 特性。

0%