聽故事學iOS系列 - 屎殼郎老板和它的收費公廁(一個故事搞懂多線程)
屎殼郎老板和它的公廁生意
屎殼郎老板在旅游區開了一間收費公廁,招待南來北往的旅客們。來上廁所的客人,都是跟著各自的旅行團來的。屎殼郎老板要求上廁所的客人一定要排好隊,一個一個來,講文明,懂禮貌,謝絕插隊和隨地大小便等不文明行為。
奇葩的旅客、奇葩的團
屎殼郎老板發現,來它這里上廁所的旅客,都非常怪異:
明明坑位很多,排隊的人也很多,可是有的時候只有一個坑位被使用,有的時候同時有好多坑位被使用。
為了弄清楚坑位的使用規律,屎殼郎老板對來上廁所的旅客,和他們所在的旅行團進行了調查統計分析。
-- 旅客篇 --
根據旅客的尿意程度,屎殼郎老板把旅客分為兩類:
- 尿急型
- 有備無患型
尿急型旅客
- 一旦前面的坑位沒人,這類旅客就會一頭扎進坑位中。
通過數據分析,屎殼郎老板還發現:
- 尿急型旅客只認準靠窗的蹲位,別的蹲位一概不去。
有備無患型旅客
這類旅客其實不是很急著上廁所,他們只是看到排隊上廁所的人多,想通過排隊等坑位的時間,來拓展自己的人脈圈的(如此高明的拓展人脈圈手段也是醉了-_-|||)
輪到他們進坑的時候,他們不會一頭扎進去,而是
- 先勾搭他后面的旅客
“嘿哥們兒,一起啊~”
看到后面的哥們準備動身了,他才動身
屎殼郎老板還發現,這類旅客:
- 一般會盡最大可能不用靠窗的坑位。
附注
由于尿急型旅客不主動招呼排在他后面的旅客,所以,后面的旅客只有親眼看到尿急旅客已經方便完從坑位出來了,才會選坑進入。
-- 旅行團篇 --
研究完旅客,屎殼郎老板又對旅客們所在的旅行團做了分析和歸類。根據旅行團印發的《關于參團游客排隊上公廁秩序的相關規定》內容進行劃分(這旅行團管的也太寬了吧-_-|||),大致可以分為三大類
- 寬松型
- 嚴格型
- 苛刻型
寬松型
團規:團內旅客盡量用最短的時間解決完上廁所問題,使用哪個坑位不做限制。
嚴格型
團規:不管有沒有空余的坑位,本團內,一次只能有一個旅客在坑位上。
苛刻型
團規:本團內的旅客,只能使用靠窗的那個坑位。
屎殼郎老板很開心,因為有了這兩份資料,他就能提前判斷出,下一次,會有幾個旅客同時進坑,以及他們分別會用幾號坑位。
屎殼郎老板的測試題
OK,屎殼郎老板收集到的情報我們已經掌握了,那么,屎殼郎老板給大家出了一份測試題,我們一起來試著分析下吧!
題目: 假設這次排隊的旅客有四個: 其中 三個來自名叫“嚴格旅行團”的嚴格型旅行團 另外兩個來自名叫“寬松旅行團”的寬松型團 根據從前到后的順序,他們分別是: * 小A同學:來自寬松團,有備無患型 * 小B同學:來自寬松團,有備無患型 * 小C同學:來自嚴格團,尿急型 * 小D同學:來自寬松團,有備無患型 * 小E同學:來自嚴格團,尿急型
模擬入坑過程
第一階段
- 輪到排在最前面的小 A 同學入坑了,由于小 A是個有備無患型的,扭過頭來招呼小 B:“嘿哥們兒~一起啊~”
- 小 B 同學也興奮的扭過頭招呼小 C:" 嘿哥們,一起啊~"
- 小 C 已經憋很久了,拔腿就準備往蹲位里沖。
- 小 B 看到小 C 準備動身了,自己也整理整理準備動身。
- 小 A 看小 B 準備動身了,自己馬上動身走向坑位。因為是有備無患型,所以小 A 討厭靠窗的1號蹲位,選擇了2號蹲位。
- 小 B 動身前也思考了一下,我們團允許多個團員同時入坑。于是小 B 也動身了。有備無患型,討厭靠窗的1號蹲位,2號蹲位又有人了,于是選擇了3號蹲位
- 雖然便意濃濃,但小 C 還是略一思忖:我們團規定一次只能一個人入坑,前面入坑的兩個都不是我們團的,看來我能入坑。然后看了一眼坑位:我喜歡的靠窗1號坑正好沒人用!然后拔腿奔向了1號坑位。
總結:第一階段同時入坑的有ABC三 位同學,分別使用了2號坑、3號坑和1號坑
第二階段
- 親眼看見小 C 從蹲位里面帶幸福的走出來,小 D 知道,輪到自己了。于是招呼小 E 一起入坑
- 小 E 二話不說低著頭就準備往坑里沖。小 D 見狀略一思忖:我們團允許多個本團成員一起入坑,雖然之前兩個團員小 A 和小 B 還沒出來(假設小 A 和小B 解決的比較慢),但我還是可以入坑的。 于是動身選坑位
- 1號坑位雖然沒人,但是小 D不喜歡,2號3號有人了(小 A 小 B 在里面),所以小 D 選擇了4號坑位
- 小 E 臨行前也簡單思考了下:我們團沒有人在蹲位中,1號蹲位沒有人。于是小 E 沖向了1號蹲位。
總結:第二階段同時入坑的有 DE 兩位同學,分別使用了4號坑和1號坑。
驗證
OK~分析完成,我們用代碼來驗證下是不是這樣~
代碼們
可以嘗試自己運行下看看結果是不是和我們分析的一樣哦!
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- {
- // 創建名叫“嚴格旅行團”的嚴格型旅行團
- dispatch_queue_t seriouslyTeam = dispatch_queue_create("com.azen.xu", DISPATCH_QUEUE_SERIAL);
- // 創建名叫“寬松旅行團”的寬松型旅行團
- dispatch_queue_t relaxingTeam = dispatch_queue_create("com.azen.xu",DISPATCH_QUEUE_CONCURRENT);
- // 創建寬松團的有備無患型小 A
- dispatch_async( relaxingTeam, ^{
- // 讓小 A 便便的時間長一點
- for (int i = 0 ; i <= 1000 ; i++)
- {
- NSLog(@"我是小 A,我在便便 -- 完成度 %%%.3f ---%@",i * 0.1,[NSThread currentThread]);
- }
- });
- // 創建與小 A 相似的小 B
- dispatch_async( relaxingTeam, ^{
- // 讓小 B 便便的時間也長一點
- for (int i = 0 ; i <= 1000 ; i++)
- {
- NSLog(@"我是小 B,我在也便便 -- 完成度 %%%.3f ---%@",i * 0.1,[NSThread currentThread]);
- }
- });
- // 創建嚴格團的尿急小 C
- dispatch_sync(seriouslyTeam, ^{
- // 小 C 便的時間短一點
- for (int i = 0 ; i <= 10 ; i++)
- {
- NSLog(@"我是小 C,我在也便便 -- 完成度 %%%d ---%@",i * 10,[NSThread currentThread]);
- }
- });
- // 寬松團的有備無患型小 D
- dispatch_async( relaxingTeam, ^{
- // 讓小 D 便便的時間也長一點
- for (int i = 0 ; i <= 1000 ; i++)
- {
- NSLog(@"我是小 D,我在也便便 -- 完成度 %%%.3f ---%@",i * 0.1,[NSThread currentThread]);
- }
- });
- // 嚴格團的尿急小 E
- dispatch_sync( seriouslyTeam, ^{
- // 讓小 E 便便的時間也長一點
- for (int i = 0 ; i <= 1000 ; i++)
- {
- NSLog(@"我是小 E,我在也便便 -- 完成度 %%%.3f ---%@",i * 0.1,[NSThread currentThread]);
- }
- });
- }
總結
嗯哼~ 故事講完了。沒看明白?不知道這鬼東西有什么卵用?不妨看看下面的對照表哦:
概念對照表
- 旅客 對應 任務
1.1 尿急型旅客 對應 同步任務
1.2 有備無患型旅客 對應 異步任務 - 旅行團 對應 隊列
2.1 寬松型旅行團 對應 并發隊列(Concurrent
Dispatch Queue)
2.2 嚴格型旅行團 對應 串行隊列(Serial
Dispatch Queue)
2.3 苛刻型旅行團 對應 主隊列(Main Queue) - 蹲位 對應 線程
3.1 靠窗蹲位 對應 主線程
(所有涉及 UI 展示方面的任務都要在主線程中執行,所以... 主線程就是靠窗的蹲位啦...)
3.2 其他蹲位 對應 子線程
應用
嘗試用多線程知識實現:分 六個任務別打印A、B、C、D、E 、F 六個字母,要求:A打印完后打印 B 和 C(要求BC幾乎同時打印),C 打印完后打印D、E、F( DEF幾乎同時打印)
最后的最后
一個故事并不能將多線程的知識完全講清楚,只是希望,這篇小小的、有點怪誕、槽點滿滿的故事,能帶給大家一點輕松快樂的好心情。會心一笑,然后帶著這份好心情,一起繼續在這個充滿魔法的編程世界里前行吧~ ^_^
PS. 剛編出來這個故事時候,每次上廁所看到蹲位都忍不住想笑... 不過想到邊排泄邊傻笑可能有點怪怪的...所以還是忍住了= =
PPS. 屎殼郎老板的故事還沒有結束哦!下一篇——《屎殼郎老板的神奇寶貝——蹲位獸》,和大家一起探秘屎殼郎老板公廁的蹲位,順便聊一點runloop的小知識^_^