IOS - 大话《多线程》

427 阅读5分钟

时间: 2月26日22点

地点: 永旺商场

背景: 隔壁空地上的商场终于建成了,大大小小的商店纷纷入驻,大A发现了商机,想开一家奶茶店,话不多说,交钱干。

一、开店(进程)

大A是个踏实肯干的人,开店之初啊,也没想那么多,就想踏踏实实挣点小钱,于是乎把自己的这些想法告诉了设计师,设计师一想,好办:

  • 1间内部操作室和一些调配机器
  • 1台收银机
  • 1个收银员+3名奶茶调配员

齐活,说干就干,不到一个月店面就装修好了,于是乎按照设计师的规划招了4个小姐姐。

2020年2月26日,随着一顿鞭炮声大A的奶茶店终于开张了,陆陆续续来了很多顾客...

我们把商场当做一个系统,那么我们的奶茶店就是一个进程,当然我们的商场还有 H&M啊、
优衣库啊,你懂的!这些店之间互不干扰,各自开门各自做生意,互不影响...

开业之初效果:

这个店(进程)就这样红红火火开起来了...

系统(System):商场
进程(Process):奶茶店
线程(Thread):员工的日常工作
进程是系统中正在运行的一个应用程序,每个进程之间是独立的
(你卖你的奶茶,我卖我的衣服,YES!)

二、员工日常工作(线程)

奶茶店每天都有很多活:

  • 进货,分装原料
  • 派单收银
  • 奶茶调配

每天我们奶茶店都要开门,只有开门了员工才能进来,才能干活,这是核心门槛(主线程),所有员工干活才让奶茶店运营起来(线程是进程的基本执行单元)

线程(thread):进程的基本执行单元,一个进程的所有任务都在线程中执行,
进程要想执行任务必须要有线程,程序会默认开启一条线程,这条线程叫‘主线程’

三、扩张(开辟新线程)

大A还是很踏实肯干的,每天卖命的吆喝,生意也是越来越好,这一天天的,人都排到马路对面了...

期间不断的有人跟大A说:老板啊,多招点人撒,搞两个收银的,排两个队,这大热天的我们等的也是很难受啊,有的人等不了就去别家买了,你也损失不是...

大A一想,也是啊,那么就试试,又找了设计师,这次相对比较简单,就是加台收银机嘛,你再额外招个小姐姐就好了,于是乎店门关了两周,终于算是装修好了: 艾玛果然好多了,至少现在顾客都能进屋吹空调了,哈哈,唯独就多招了一个收银小姐姐而已,这买卖划算啊...

3.1 同时派单出错

由于每天的原料有限,而且不同的品种的奶茶数量也是有限的,经常小B刚派了一杯🍑🍑🍑口味的,小C也派了一杯🍑🍑🍑口味的,后台一看,MMP

于是乎,后台就给两位小姐姐提了个idea,你们卖奶茶的时候提前问一下(加锁)我这边还能做几杯,能做就走单,不能就告知客户,哦了,屌屌的。

3.2 圆桌区域变小

但是有的顾客又提问题了,现在倒是好排队了,但是买了也没地方坐了,原来新的队列占了原来圆桌的区域,导致圆桌变少了,没办法嘛,商场就给我分配这么大的空间,空间有限呀,只能少两张桌子了,也是为了大家更快的喝上奶茶嘛,坐哪重要吗?哈哈!

3.3 员工很累

开始几天搞促销,大伙热热烈烈的,几天之后小姐姐B就开始抱怨了,现在两个收银员一起派单,还是我们三个人来配料。真的是...

3.4 死锁

有一天后台调配师小C和收银小B闹矛盾了,讲道理是不可能讲道理了:

老板一听,你俩玩起死锁来了,我这店还开个锤子哦~

通过上面种种,我们分析多线程的优缺点得出:

多线程优点
- 开辟线程能提高程序执行效率(派单更快了)
- 能适当提高资源利用率CPU,内存(后台都可以忙活起来)
- 线程上的任务执行完后,线程会自动销毁(某一队没人了,收银员小姐姐就开始刷抖音了)
多线程缺点
- 开辟线程需要占用一定的内存空间(圆桌区域变小了)
- 程序更加复杂,线程间通讯,多线程数据共享(同时派单问题,加锁问题)
- 开启大量线程,会占用大量内存空间,降低程序性能(小姐姐表示好累)
- 线程越多CPU在线程上的开销越大(小姐姐不够用了,需要更多的小姐姐来配合)

四、总结

至此我们关于进程和线程的故事讲的差不多了,你弄明白了吗,下面我们补充一些其他的知识点。

4.1 线程生命周期

  • 新建
  • 就绪
  • 运行
  • 阻塞
  • 死亡

4.2 线程创建策略

话不多说,图示很详细:

4.3 线程和runloop的关系

  1. runloop与线程是一一对应的,一个runloop对应一个核心线程。
  2. runoop是用来管理线程的,当线程的runloop被开启后,线程会在执行任务完毕后进入休眠状态,当有了新任务的时候就会被唤醒去执行任务。
  3. runloop在第一次获取时被创建,在线程结束时被销毁。
  4. 对于主线程来说,runloop在程序一启动就默认创建好了。
  5. 对于子线程来说,runloop是懒加载的,只有当我们使用时才创建,所以子线程在使用定时器的时候要确保子线程的runloop被创建,不然定时器不会回调。

后面我会针对GCD以及各种锁来详述多线程的原理和实线,敬请期待,写的不好,希望多多赐教和点评,谢谢。