iOS GCD相關使用方法

1.GCD簡介

Grand Central Dispatch(GCD) 是 Apple 開發(fā)的一個多核編程的較新的解決方法博个。它主要用于優(yōu)化應用程序以支持多核處理器以及其他對稱多處理系統(tǒng)。它是一個在線程池模式的基礎上執(zhí)行的并發(fā)任務功偿。在 Mac OS X 10.6 雪豹中首次推出盆佣,也可在 iOS 4 及以上版本使用。

GCD優(yōu)點

  • GCD可用于多核的并行運算
  • GCD會利用更多的CPU內(nèi)核
  • GCD會自動管理線程的生命周期

2.GCD任務和隊列

同步執(zhí)行(sync)

  • 同步添加到指定的隊列中械荷,再添加的任務執(zhí)行結束前共耍,一直等待,在隊列里的任務執(zhí)行完成后在執(zhí)行
  • 不具備開啟線程的能力吨瞎,在當前線程中執(zhí)行痹兜。

異步執(zhí)行

  • 異步任務添加到隊列中,不會等待颤诀,可以繼續(xù)執(zhí)行字旭。
  • 可以下新的線程中執(zhí)行任務。

隊列: 用來存放任務的隊列崖叫。隊列是一種特殊的線性表遗淳,采用FIFO(先進先出)的原則。

  • 串行隊列:每次只有一個任務會被執(zhí)行心傀,當一個任務執(zhí)行完成后在執(zhí)行下一個任務
  • 并發(fā)隊列:可以讓多個任務同時執(zhí)行屈暗。可以開啟多個線程脂男,同時執(zhí)行任務恐锦。

3.創(chuàng)建隊列

  • 串行隊列
     /*
     *串行隊列
     *參數(shù)1:線程名稱可以為空測試時可用
     *參數(shù)2:串行隊列
     */
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL);
  • 并發(fā)隊列
 /*
     *并發(fā)隊列
     *參數(shù)1:線程名稱可以為空測試時可用
     *參數(shù)2:并發(fā)隊列
     */
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
  • 對于串行隊列,GCD提供了一種特殊的串行隊列主隊列(Main Dispatch Queue)
    • 所有放到主隊列中的任務疆液,都會放到主線程中執(zhí)行一铅。
    • dispatch_get_main_queue()獲取主隊列。
dispatch_queue_t queue = dispatch_get_main_queue();
  • 并發(fā)隊列堕油,GCD默認提供了全局并發(fā)隊列
/*
     *參數(shù)一 表示線程優(yōu)先級
     *參數(shù)二 0即可
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4.GCD的基本使用

  • 同步執(zhí)行 + 并發(fā)隊列:
    不會開啟新的線程潘飘,在當前線程執(zhí)行,執(zhí)行完一個任務后在執(zhí)行下一個掉缺。
NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當前線程
    NSLog(@"syncConcurrent---begin");
    
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3----%@",[NSThread currentThread]);
        }
    });
    
    NSLog(@"syncConcurrent---end");

//打印信息
2018-12-10 15:21:27.866589+0800 GCD[11895:5222420] currentThread---<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:27.866688+0800 GCD[11895:5222420] syncConcurrent---begin
2018-12-10 15:21:29.867784+0800 GCD[11895:5222420] 1----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:31.869445+0800 GCD[11895:5222420] 1----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:33.871222+0800 GCD[11895:5222420] 2----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:35.872828+0800 GCD[11895:5222420] 2----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:37.874443+0800 GCD[11895:5222420] 3----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:39.876046+0800 GCD[11895:5222420] 3----<NSThread: 0x1c0066c80>{number = 1, name = main}
2018-12-10 15:21:39.876239+0800 GCD[11895:5222420] syncConcurrent---end
  • 異步執(zhí)行+并發(fā)隊列:
    會開啟新線程卜录,所有任務同步執(zhí)行。
NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當前線程
    NSLog(@"syncConcurrent---begin");
    
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3----%@",[NSThread currentThread]);
        }
    });
    
    NSLog(@"syncConcurrent---end");
//打印信息
2018-12-10 15:22:58.596939+0800 GCD[11898:5223017] currentThread---<NSThread: 0x1c4069140>{number = 1, name = main}
2018-12-10 15:22:58.597029+0800 GCD[11898:5223017] syncConcurrent---begin
2018-12-10 15:22:58.597099+0800 GCD[11898:5223017] syncConcurrent---end
2018-12-10 15:23:00.603383+0800 GCD[11898:5223043] 2----<NSThread: 0x1c4075ac0>{number = 4, name = (null)}
2018-12-10 15:23:00.603419+0800 GCD[11898:5223041] 1----<NSThread: 0x1c0467340>{number = 3, name = (null)}
2018-12-10 15:23:00.603645+0800 GCD[11898:5223042] 3----<NSThread: 0x1c407af40>{number = 5, name = (null)}
2018-12-10 15:23:02.606575+0800 GCD[11898:5223042] 3----<NSThread: 0x1c407af40>{number = 5, name = (null)}
2018-12-10 15:23:02.608954+0800 GCD[11898:5223043] 2----<NSThread: 0x1c4075ac0>{number = 4, name = (null)}
2018-12-10 15:23:02.609031+0800 GCD[11898:5223041] 1----<NSThread: 0x1c0467340>{number = 3, name = (null)}
  • 同步執(zhí)行+串行隊列
    不會開啟新的線程眶明,在當前線程執(zhí)行任務艰毒,任務是串行,在執(zhí)行完成后一個任務在執(zhí)行下一個任務搜囱。
NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當前線程
    NSLog(@"syncConcurrent---begin");
    
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_sync(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3----%@",[NSThread currentThread]);
        }
    });
    
    NSLog(@"syncConcurrent---end");
//打印信息
2018-12-10 15:25:54.043186+0800 GCD[11901:5223884] currentThread---<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:25:54.043275+0800 GCD[11901:5223884] syncConcurrent---begin
2018-12-10 15:25:56.044897+0800 GCD[11901:5223884] 1----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:25:58.046774+0800 GCD[11901:5223884] 1----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:26:00.048408+0800 GCD[11901:5223884] 2----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:26:02.050100+0800 GCD[11901:5223884] 2----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:26:04.051480+0800 GCD[11901:5223884] 3----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:26:06.054114+0800 GCD[11901:5223884] 3----<NSThread: 0x1c007f000>{number = 1, name = main}
2018-12-10 15:26:06.054304+0800 GCD[11901:5223884] syncConcurrent---end
  • 異步執(zhí)行 + 串行隊列
    會開啟新的線程丑瞧,但是任務是串行執(zhí)行柑土,執(zhí)行完成一個任務在執(zhí)行下一個任務。
NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印當前線程
    NSLog(@"syncConcurrent---begin");
    
    dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2----%@",[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i<2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3----%@",[NSThread currentThread]);
        }
    });
    
    NSLog(@"syncConcurrent---end");
//打印信息
2018-12-10 15:27:46.578929+0800 GCD[11904:5224555] currentThread---<NSThread: 0x1c007f840>{number = 1, name = main}
2018-12-10 15:27:46.579018+0800 GCD[11904:5224555] syncConcurrent---begin
2018-12-10 15:27:46.579133+0800 GCD[11904:5224555] syncConcurrent---end
2018-12-10 15:27:48.585620+0800 GCD[11904:5224577] 1----<NSThread: 0x1c0479980>{number = 3, name = (null)}
2018-12-10 15:27:50.590468+0800 GCD[11904:5224577] 1----<NSThread: 0x1c0479980>{number = 3, name = (null)}
2018-12-10 15:27:52.596004+0800 GCD[11904:5224577] 2----<NSThread: 0x1c0479980>{number = 3, name = (null)}
2018-12-10 15:27:54.601597+0800 GCD[11904:5224577] 2----<NSThread: 0x1c0479980>{number = 3, name = (null)}
2018-12-10 15:27:56.607246+0800 GCD[11904:5224577] 3----<NSThread: 0x1c0479980>{number = 3, name = (null)}
2018-12-10 15:27:58.610236+0800 GCD[11904:5224577] 3----<NSThread: 0x1c0479980>{number = 3, name = (null)}
  • 同步執(zhí)行 + 主隊列(在主線程):
    出現(xiàn)死鎖绊汹,相互等待卡主不執(zhí)行稽屏。syncMain任務放到主線程中隊列執(zhí)行。同步執(zhí)行會等待當前隊列中的任務執(zhí)行完成后才會執(zhí)行
  • 異步執(zhí)行 + 主隊列 :
    在主線程中執(zhí)行任務西乖,執(zhí)行完成一個任務后再執(zhí)行下一個任務狐榔。

5.GCD信號量

  • 當我們在進行網(wǎng)絡請求是,需要在一個請求執(zhí)行完成后再去執(zhí)行下一個請求是获雕,因為網(wǎng)絡請求是異步執(zhí)行薄腻,需要用到信號量。當信號量為0的時候就會阻塞線程届案,大于0的時候就不會阻塞線程被廓,通過改變信號量的值就可以控制線程。

  • dispatch_semaphore_create 創(chuàng)建信號量

  • dispatch_semaphore_signal
    1.返回值long類型萝玷,當返回值為0時,表示當前沒有線程等待處理的信號昆婿,信號量增加1球碉。
    2.當返回值不為0時,表示當前有一個會多個線程等待處理的信號量仓蛆,并且該函數(shù)喚醒了一個等待的線程睁冬。

  • dispatch_semaphore_wait
    1.等待信號,判斷信號量是否大于0看疙,如果大于0就減掉1個信號往下執(zhí)行豆拨。
    2.如果等于0函數(shù)就會阻塞當前的線程。

//創(chuàng)建信號量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    NSLog(@"開始網(wǎng)絡請求");
    
    [[SetNetWorking baseHttpManager] upLoadDataImage:image successBlock:^(id response) {
        //信號量+1
        
        NSLog(@"正在網(wǎng)絡請求");
        
        dispatch_semaphore_signal(semaphore);
        if (response) {
            
        }else{
            
        }
    } failedBlock:^(NSError * _Nonnull error) {
        dispatch_semaphore_signal(semaphore);
        [ToastView toastWithNSString:@"上傳圖片失敗"];
    }];
    //信號量為0的時候回阻塞線程
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    
    NSLog(@"網(wǎng)絡請求完成");

//打印信息

6.GCD 隊列組:dispatch_group

  • 創(chuàng)建隊列組dispatch_group_t group = dispatch_group_create();
dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Request_1");
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Request_2");
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Request_3");
    });
    //隊列組執(zhí)行完后執(zhí)行
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任務均完成能庆,刷新界面");
    });

但是在進行網(wǎng)絡請求是施禾,請求都是異步執(zhí)行,要實現(xiàn)在所有請求執(zhí)行完成后再執(zhí)行后面的任務需要用到dispatch_group_enter(group)dispatch_group_leave(group)

  • dispatch_group_enter 標志著一個任務追加到 group搁胆,執(zhí)行一次弥搞,相當于 group 中未執(zhí)行完畢任務數(shù)+1
  • dispatch_group_leave 標志著一個任務離開了 group,執(zhí)行一次渠旁,相當于 group 中未執(zhí)行完畢任務數(shù)-1
  • 當 group 中未執(zhí)行完畢任務數(shù)為0的時候攀例,才會使dispatch_group_wait解除阻塞,以及執(zhí)行追加到dispatch_group_notify中的任務

dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //請求1
        [網(wǎng)絡請求:{
            成功:dispatch_group_leave(group);
            失敗:dispatch_group_leave(group);
        }];
    });
    dispatch_group_enter(group);
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [網(wǎng)絡請求:{
            成功:dispatch_group_leave(group);
            失敗:dispatch_group_leave(group);
        }];
    });
    dispatch_group_enter(group);
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [網(wǎng)絡請求:{
            成功:dispatch_group_leave(group);
            失敗:dispatch_group_leave(group);
        }];
    });
    //隊列組執(zhí)行完后執(zhí)行
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"任務均完成顾腊,刷新界面");
    });
  • dispatch_group_wait會阻塞當前線程粤铭,當組中多有任務完成后再執(zhí)行下面任務

GCD柵欄

dispatch_barrier_async在異步執(zhí)行兩組操作,需要實現(xiàn)在執(zhí)行完一組后在執(zhí)行一組是需要使用到柵欄

7.GCD定時器

__block NSInteger time = 10; //倒計時時間
    
    //創(chuàng)建全局隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //使用全局隊列創(chuàng)建計時器
    dispatch_source_t sourceTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    /*
     *參數(shù)一:傳入計時器
     *參數(shù)二:計時器開始時間
     *參數(shù)三:計時器間隔時間
     *參數(shù)四:代表精準度杂靶,0是最精確
    */
    dispatch_source_set_timer(sourceTimer, DISPATCH_TIME_NOW, 1.0*NSEC_PER_SEC, 0);
    //開始執(zhí)行計時器任務
    dispatch_source_set_event_handler(sourceTimer, ^{
        if (time<=0) {
            //計時器關閉
            dispatch_source_cancel(sourceTimer);
            NSLog(@"執(zhí)行完成");
        }else{
            NSLog(@"%ld",time);
        }
        time --;
    });
    
    //開始執(zhí)行計時器任務
    dispatch_resume(sourceTimer);

8.GCD一次性代碼只執(zhí)行一次梆惯。

  • 我們在創(chuàng)建單例酱鸭、或者有整個程序運行過程中只執(zhí)行一次的代碼時,我們就用到了 GCD 的dispatch_once 函數(shù)加袋。使用
    dispatch_once 函數(shù)能保證某段代碼在程序運行過程中只被執(zhí)行1次凛辣,并且即使在多線程的環(huán)境下,dispatch_once也可以保證線程安全职烧。
/**
 * 一次性代碼(只執(zhí)行一次)dispatch_once
 */
- (void)once {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 只執(zhí)行1次的代碼(這里面默認是線程安全的)
    });
}

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扁誓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚀之,更是在濱河造成了極大的恐慌蝗敢,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件足删,死亡現(xiàn)場離奇詭異寿谴,居然都是意外死亡,警方通過查閱死者的電腦和手機失受,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門讶泰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拂到,你說我怎么就攤上這事痪署。” “怎么了兄旬?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵狼犯,是天一觀的道長。 經(jīng)常有香客問我领铐,道長悯森,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任绪撵,我火速辦了婚禮瓢姻,結果婚禮上,老公的妹妹穿的比我還像新娘音诈。我一直安慰自己汹来,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布改艇。 她就那樣靜靜地躺著收班,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谒兄。 梳的紋絲不亂的頭發(fā)上摔桦,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼邻耕。 笑死鸥咖,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的兄世。 我是一名探鬼主播啼辣,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼御滩!你這毒婦竟也來了鸥拧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤削解,失蹤者是張志新(化名)和其女友劉穎富弦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氛驮,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡腕柜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矫废。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盏缤。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蓖扑,靈堂內(nèi)的尸體忽然破棺而出唉铜,到底是詐尸還是另有隱情,我是刑警寧澤赵誓,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站柿赊,受9級特大地震影響俩功,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碰声,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一诡蜓、第九天 我趴在偏房一處隱蔽的房頂上張望瞧柔。 院中可真熱鬧班巩,春花似錦、人聲如沸荠耽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贡这,卻和暖如春茬末,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工丽惭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留击奶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓责掏,卻偏偏與公主長得像柜砾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子换衬,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 文用來介紹 iOS 多線程中 GCD 的相關知識以及使用方法痰驱。通過本文,您將了解到: 1. GCD 簡介 2. G...
    曉_我想去環(huán)游世界閱讀 1,146評論 2 8
  • 本文用來介紹 iOS 多線程中 GCD 的相關知識以及使用方法冗疮。這大概是史上最詳細萄唇、清晰的關于 GCD 的詳細講...
    花花世界的孤獨行者閱讀 502評論 0 1
  • 昨日開懷 今日歡笑 隨遇而安也不失調(diào) 心有陽光 處處皆美好 上山砍柴 下山歇腳 看炊煙娜娜裊裊 逢河搭橋 冷暖自斷...
    海之貝閱讀 303評論 0 1
  • 這兩天無聊把劉德華主演的一部老電影《五億探長雷洛傳》看了,講述了一個香港警察從理想青年變成一代梟雄的過程术幔,現(xiàn)記下一...
    一個人的城圍閱讀 6,228評論 1 0
  • 多年沒見另萤,你一點沒變。 你文靜的坐著 眼睛里的亮光來自遠方 我們被人流隔開 他們嗡嗡嗡的發(fā)出噪聲 我試圖去靠近你 ...
    子夜玄白閱讀 201評論 2 2