多線程總結(jié)之GCD

多線程有幾個(gè)重要的概念青伤,任務(wù)、隊(duì)列殴瘦、線程狠角。
任務(wù):是指執(zhí)行什么樣的操作,在GCD中就是block蚪腋。
隊(duì)列:用來(lái)存放任務(wù)丰歌,分為串行隊(duì)列和并行隊(duì)列。放在串行隊(duì)列中的任務(wù)要等到正在執(zhí)行的任務(wù)執(zhí)行完后才會(huì)被執(zhí)行屉凯;放在并行隊(duì)列中的任務(wù)不用等到正在執(zhí)行的任務(wù)執(zhí)行完就可以被執(zhí)行立帖。
線程:執(zhí)行任務(wù)需要線程,線程從隊(duì)列中以先進(jìn)先出(FIFO)的方式取出任務(wù)執(zhí)行神得,線程一次只能執(zhí)行一個(gè)任務(wù)厘惦。
這三者的關(guān)系就是:線程從隊(duì)列中取任務(wù)執(zhí)行。

GCD中的隊(duì)列:
dispatch_main_queue 主隊(duì)列哩簿,程序啟動(dòng)時(shí)與主線程一起由系統(tǒng)自動(dòng)創(chuàng)建宵蕉,UI操作都放在主隊(duì)列中
dispatch_get_global_queu 全局并發(fā)隊(duì)列,由系統(tǒng)定義节榜,調(diào)用函數(shù)dispatch_get_global_queue(identifier: Int, flags: Uint)獲取羡玛。identifier以前叫做優(yōu)先級(jí),現(xiàn)在稱為服務(wù)質(zhì)量宗苍,現(xiàn)在傳入優(yōu)先級(jí)的宏定義也可以稼稿,目測(cè)優(yōu)先級(jí)的界限并不明顯,所以平時(shí)直接傳入0讳窟,見(jiàn)下面對(duì)應(yīng)關(guān)系让歼。flags是系統(tǒng)保留的一個(gè)參數(shù),傳入0即可丽啡。

DISPATCH_QUEUE_PRIORITY_HIGH        QOS_CLASS_USER_INITIATED       2
DISPATCH_QUEUE_PRIORITY_DEFAULT     QOS_CLASS_DEFAULT              0
DISPATCH_QUEUE_PRIORITY_LOW         QOS_CLASS_UTILITY             -2
DISPATCH_QUEUE_PRIORITY_BACKGROUND  QOS_CLASS_BACKGROUND           INT16_MIN

對(duì)于同一優(yōu)先級(jí)谋右,獲取到的全局并發(fā)隊(duì)列是同一個(gè); 不同優(yōu)先級(jí),獲取到的全局并發(fā)隊(duì)列也不同补箍「闹矗看下面獲取全局并發(fā)隊(duì)列

NSLog(@"%@",dispatch_get_global_queue(0, 0));
NSLog(@"%@",dispatch_get_global_queue(0, 0));
NSLog(@"%@",dispatch_get_global_queue(2, 0));
NSLog(@"%@",dispatch_get_global_queue(2, 0));
運(yùn)行結(jié)果
dispatch_queue_create(<#const char * _Nullable label#>, <#dispatch_queue_attr_t  _Nullable attr#>)

開(kāi)發(fā)者自己創(chuàng)建的隊(duì)列,參數(shù)label是該隊(duì)列的名字坑雅,可以通過(guò)

dispatch_queue_get_label(<#dispatch_queue_t  _Nullable queue#>)

獲取辈挂。參數(shù)attr傳入DISPATCH_QUEUE_SERIAL或nil返回串行隊(duì)列,傳入DISPATCH_QUEUE_CONCURRENT返回并行隊(duì)列裹粤。
dispatch_queue_create 創(chuàng)建的優(yōu)先級(jí)與全局并發(fā)隊(duì)列的默認(rèn)優(yōu)先級(jí)是同一級(jí)別终蒂,也就是說(shuō)創(chuàng)建的隊(duì)列的優(yōu)先級(jí)為默認(rèn)優(yōu)先級(jí)。至于怎么改變它的優(yōu)先級(jí)需要調(diào)用dispatch_set_target_queue,這個(gè)函數(shù)后面描述后豫。

調(diào)度函數(shù)

dispatch_sync 將任務(wù)提交到相應(yīng)隊(duì)列悉尾,同步執(zhí)行,不開(kāi)新線程
dispatch_async 將任務(wù)提交到相應(yīng)隊(duì)列挫酿,異步執(zhí)行构眯,如果從主隊(duì)列取任務(wù),不開(kāi)新線程早龟,在主線程中執(zhí)行惫霸;其他隊(duì)列,開(kāi)新線程執(zhí)行
現(xiàn)在來(lái)看看調(diào)度函數(shù)與各種隊(duì)列的組合后的情況:
1葱弟、dispatch_sync 與 串行隊(duì)列:
(1)在串行隊(duì)列queue中調(diào)用該函數(shù)壹店、且該函數(shù)是從串行隊(duì)列queue中去任務(wù)執(zhí)行,就會(huì)出現(xiàn)線程死鎖芝加。 例如下面兩種情況:

在主線程中調(diào)用

dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"在主線程中調(diào)用dispatch_sync硅卢,并且該函數(shù)第一個(gè)參數(shù)傳入的是主隊(duì)列,則會(huì)出現(xiàn)線程死鎖");
    });

在同步執(zhí)行任務(wù)的子線程中調(diào)用

dispatch_queue_t queue = dispatch_queue_create("串行隊(duì)列", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        /*
         其他代碼
         */
        dispatch_sync(queue, ^{
            NSLog(@"queue是串行隊(duì)列就會(huì)出現(xiàn)線程死鎖");
        });
    });

(2)該串行隊(duì)列與當(dāng)前隊(duì)列不同藏杖,不會(huì)出現(xiàn)線程死鎖将塑。在當(dāng)前線程中同步執(zhí)行。dispatch_sync執(zhí)行完后它后面的代碼才會(huì)執(zhí)行蝌麸。

2点寥、dispatch_sync 與 并行隊(duì)列:
因?yàn)閐ispatch_sync不開(kāi)線程,并且線程一次只能執(zhí)行一個(gè)任務(wù)来吩,所以依然是敢辩,dispatch_sync執(zhí)行完后它后面的代碼才會(huì)執(zhí)行。
3弟疆、dispatch_async 與 串行隊(duì)列:
(1)主隊(duì)列戚长,不開(kāi)新線程,任務(wù)將在主線程中執(zhí)行怠苔。但不會(huì)馬上執(zhí)行同廉,而是將任務(wù)從棧copy到堆,等待主隊(duì)列中棧區(qū)的任務(wù)執(zhí)行完嘀略,再執(zhí)行堆區(qū)的任務(wù)恤溶。因此

dispatch_async(dispatch_get_main_queue(), ^{
        /*
         在主線程執(zhí)行任務(wù)
         */
    });

有兩個(gè)作用:1)子線程處理耗時(shí)操作后回到主線程處理UI; 2)延時(shí)乓诽。
(2)開(kāi)發(fā)者創(chuàng)建的串行隊(duì)列帜羊,開(kāi)新線程同步執(zhí)行。
4鸠天、dispatch_async 與 并發(fā)隊(duì)列:
開(kāi)新線程并發(fā)執(zhí)行任務(wù)讼育,至于開(kāi)多少條線程由系統(tǒng)決定。看下面的代碼以及運(yùn)行結(jié)果:

for (int i = 0; i < 20; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"線程%@執(zhí)行第%d個(gè)任務(wù)",[NSThread currentThread],i);
    });
}
運(yùn)行結(jié)果 number從3到14奶段,新開(kāi)線程個(gè)數(shù)<20

dispatch_after 延時(shí)操作,調(diào)用函數(shù)

dispatch_after(<#dispatch_time_t when#>, <#dispatch_queue_t  _Nonnull queue#>, <#^(void)block#>)

參數(shù)when 指定時(shí)間饥瓷,傳入DISPATCH_TIME_NOW,效果等同于dispatch_async痹籍;傳入DISPATCH_TIME_FOREVER呢铆,任務(wù)將永不執(zhí)行;所以一般傳入dispatch_time(DISPATCH_TIME_NOW, (int64_t)(t * NSEC_PER_SEC))
t*NSEC_PER_SEC代表t秒蹲缠。
參數(shù)queue可以是任意隊(duì)列棺克,一般傳入主隊(duì)列。

dispatch_group 調(diào)度組
幾個(gè)任務(wù)并發(fā)執(zhí)行线定,并且等到都執(zhí)行完后再做其他操作娜谊,就可調(diào)使用該函數(shù)。例如異步下載小說(shuō)A斤讥、B纱皆、C,下載完后提示用戶芭商,代碼如下:

    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)A");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)B");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"下載小說(shuō)C");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"所有小說(shuō)下載完成");
    });
運(yùn)行結(jié)果

也可將

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"所有小說(shuō)下載完成");
});

替換成

BOOL flag = dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if (flag) {
    NSLog(@"所有小說(shuō)下載完成");
} else {
    NSLog(@"小說(shuō)下載超時(shí)");
}

dispatch_group_wait的第二個(gè)參數(shù)可傳入指定時(shí)間派草。

dispatch_once 一次性操作
調(diào)用函數(shù)

dispatch_once(<#dispatch_once_t * _Nonnull predicate#>, <#^(void)block#>)

參數(shù)predicate 是用來(lái)標(biāo)識(shí)block是否執(zhí)行的指針,必須是全局或靜態(tài)變量蓉坎,并且該指針?biāo)赶虻膮^(qū)域的初始值為0澳眷,當(dāng)任務(wù)執(zhí)行完畢,系統(tǒng)會(huì)將其值置為-1蛉艾。
這個(gè)函數(shù)用于初始化全局?jǐn)?shù)據(jù)钳踊,并且保證線程安全,常用于OC中的單例模式勿侯。
dispatch_apply dispatch_sync 與 dispatch_group 的結(jié)合

調(diào)用函數(shù)

dispatch_apply(<#size_t iterations#>, <#dispatch_queue_t  _Nonnull queue#>, <#^(size_t)block#>)

參數(shù) iterations 將任務(wù)循環(huán)添加到指定隊(duì)列的次數(shù)拓瞪; block的參數(shù)是循環(huán)下標(biāo)(從0開(kāi)始)
調(diào)用該函數(shù)會(huì)將queue中的任務(wù)執(zhí)行完才執(zhí)行它后面的代碼。queue如果是串行隊(duì)列助琐,queue中的任務(wù)會(huì)在當(dāng)前線程中同步執(zhí)行荞膘;queue如果是并行隊(duì)列,當(dāng)前線程會(huì)取出queue中的第一個(gè)任務(wù)執(zhí)行卡辰,然后開(kāi)新線程執(zhí)行后面的任務(wù)钠右,所開(kāi)線程個(gè)數(shù)由系統(tǒng)決定。因?yàn)閐ispatch_apply具有dispatch_sync的特征掘譬,所以如果queue是串行隊(duì)列并且與當(dāng)前的隊(duì)列是同一個(gè)對(duì)象時(shí)泰演,就會(huì)出現(xiàn)線程死鎖。
dispatch_apply主要用于異步并發(fā)處理數(shù)據(jù)葱轩,并且處理完后統(tǒng)一操作睦焕。所以dispatch_apply一般在子線程中調(diào)用藐握。當(dāng)然,像這樣的操作用dispatch_group也可以實(shí)現(xiàn)垃喊。但是猾普,思考這種情況,如果對(duì)象數(shù)組本谜,里面所有元素需要并發(fā)執(zhí)行某種操作初家,并且都執(zhí)行完之后要統(tǒng)一做處理,這時(shí)如果用dispatch_group乌助,則需要for in 遍歷數(shù)組笤成,用dispatch_apply則可以省去這種遍歷。代碼如下:

dispatch_async(queue, ^{
    dispatch_apply(arr.count, dispatch_get_global_queue(0, 0), ^(size_t i) {
        NSLog(@"%@",arr[i]);
    });
});

dispatch_barrier_async 在處理數(shù)據(jù)讀取時(shí)眷茁,為了避免數(shù)據(jù)競(jìng)爭(zhēng)的問(wèn)題炕泳,寫(xiě)入操作與寫(xiě)入操作或讀取操作不能并發(fā)執(zhí)行。針對(duì)這個(gè)例子上祈,可以使用dispatch_barrier_async將寫(xiě)入操作提交到并發(fā)隊(duì)列中培遵,此時(shí)被提交的任務(wù)暫不執(zhí)行,當(dāng)他前面的任務(wù)執(zhí)行完畢時(shí)在執(zhí)行該任務(wù)登刺,等到該任務(wù)執(zhí)行完畢籽腕,后面提交的才執(zhí)行。需要注意的是指定的queue應(yīng)該是通過(guò)dispatch_queue_create創(chuàng)建的纸俭,系統(tǒng)定義的全局并發(fā)隊(duì)列無(wú)效皇耗。示例代碼如下:

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    NSLog(@"讀取操作1");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作2");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作3");
});
dispatch_barrier_async(queue, ^{
    NSLog(@"寫(xiě)入操作1");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作4");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作5");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作6");
});
dispatch_barrier_async(queue, ^{
    NSLog(@"寫(xiě)入操作2");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作7");
});
dispatch_async(queue, ^{
    NSLog(@"讀取操作8");
});

運(yùn)行結(jié)果

與之對(duì)應(yīng)的是dispatch_barrier_sync,該函數(shù)會(huì)阻塞當(dāng)前線程揍很。它也會(huì)等待前面提交的任務(wù)執(zhí)行完畢在執(zhí)行該函數(shù)提交的任務(wù)郎楼,等它執(zhí)行完畢后面的任務(wù)才提交到queue中執(zhí)行

dispatch_semaphore 信號(hào)量。 簡(jiǎn)單來(lái)說(shuō)就是控制訪問(wèn)資源的數(shù)量窒悔,比如系統(tǒng)有兩個(gè)資源可以被利用呜袁,同時(shí)有三個(gè)線程要訪問(wèn),只能允許兩個(gè)線程訪問(wèn)简珠,第三個(gè)應(yīng)當(dāng)?shù)却Y源被釋放后再訪問(wèn)阶界。
下面逐一介紹與之相關(guān)的三個(gè)函數(shù):
(1)dispatch_semaphore_create(<#long value#>) 創(chuàng)建信號(hào)量,返回值類型dispatch_semaphore_t
參數(shù)value 為允許訪問(wèn)資源的線程數(shù)聋庵,該值必須 >= 0膘融,否則會(huì)返回nil。當(dāng)value為0時(shí)對(duì)訪問(wèn)資源的線程沒(méi)有限制祭玉。
(2)dispatch_semaphore_signal(<#dispatch_semaphore_t _Nonnull dsema#>) 信號(hào)量+1
(3)dispatch_semaphore_wait(<#dispatch_semaphore_t _Nonnull dsema#>, <#dispatch_time_t timeout#> 該函數(shù)會(huì)讓信號(hào)量-1

這個(gè)函數(shù)的具體作用是這樣的氧映,如果dsema信號(hào)量的值大于0,該函數(shù)所處線程就繼續(xù)執(zhí)行下面的語(yǔ)句攘宙,并且將信號(hào)量的值減1屯耸,返回值為0;如果desema的值為0蹭劈,那么這個(gè)函數(shù)就阻塞當(dāng)前線程等待timeout疗绣,如果等待的期間desema的值被dispatch_semaphore_signal函數(shù)加1了,且該函數(shù)所處線程獲得了信號(hào)量铺韧,那么就繼續(xù)向下執(zhí)行并將信號(hào)量減1, 返回值為0多矮。如果等待期間沒(méi)有獲取到信號(hào)量或者信號(hào)量的值一直為0,那么等到timeout時(shí)哈打,其所處線程自動(dòng)執(zhí)行其后語(yǔ)句塔逃,返回值大于0。通過(guò)返回值是否為0料仗,可以判斷等待是否超時(shí)湾盗。

第二個(gè)函數(shù)和第一個(gè)函數(shù)是配套使用的,使用時(shí)先調(diào)用函數(shù)(3)將信號(hào)量-1立轧,后調(diào)用函數(shù)(2)將信號(hào)量+1

為了加深理解格粪,舉一個(gè)在餐廳排隊(duì)吃放的例子。假設(shè)某餐廳有50個(gè)座位氛改,這相當(dāng)于調(diào)用dispatch_semaphore_wait(value: Int)參數(shù)傳入50帐萎,有顧客來(lái)吃飯相當(dāng)于函數(shù)dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t),前50個(gè)顧客都有座位直接就餐胜卤。第51個(gè)顧客來(lái)到時(shí)就需要等待前面的顧客吃完飯離開(kāi)疆导,他才能就坐用餐。此時(shí)相當(dāng)于dispatch_semaphore_wait函數(shù)阻塞當(dāng)前線程葛躏。當(dāng)有顧客用餐完畢離開(kāi)時(shí)澈段,此時(shí)就有了一個(gè)空位。相當(dāng)于dispatch_semaphore_signal將型號(hào)來(lái)加1舰攒,第51個(gè)顧客等到座位均蜜,相當(dāng)于dispatch_semaphore_wait返回值為0。

信號(hào)量是GCD同步的一種方式芒率。前面介紹過(guò)dispatch_barrier_async是對(duì)queue中的任務(wù)進(jìn)行批量同步處理囤耳,dispatch_sync是對(duì)queue中的任務(wù)單個(gè)同步處理,而dispatch_semaphore是對(duì)queue中的某個(gè)任務(wù)中的某部分(某段代碼)同步處理偶芍。此時(shí)將dispatch_semaphore_wait中的參數(shù)傳入1充择。
dispatch_semaphore 的使用如下:

for (int i = 0; i < 100; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        /*
         其他并發(fā)操作
        */
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        /*
         同步操作,例如 [arr addObject:@(i)];
         */
        [arr addObject:@(i)];
        dispatch_semaphore_signal(semaphore);
        /*
         其他并發(fā)操作
         */
    });
}

dispatch_suspend / dispatch_resume 暫停指定的隊(duì)列 / 恢復(fù)指定的隊(duì)列
有時(shí)候獲取希望提交到queue中的任務(wù)暫不執(zhí)行匪蟀,等待某一時(shí)刻執(zhí)行椎麦,這時(shí)候就可使用dispatch_suspend 和 dispatch_resume, 使用dispatch_suspend時(shí)對(duì)正在執(zhí)行的任務(wù)不會(huì)起作用。

dispatch_suspend使指定隊(duì)列的暫停計(jì)數(shù)+1观挎,dispatch_resume使指定隊(duì)列的暫停計(jì)數(shù)-1。
使用它們時(shí)要注意幾點(diǎn):
(1)dispatch_suspend 與 dispatch_resume 成對(duì)出現(xiàn) 造成,否則程序在運(yùn)行時(shí)會(huì)crash
(2)dispatch_suspend 與 dispatch_resume 中指定的隊(duì)列是通過(guò) dispatch_queue_create 創(chuàng)建的晒屎,其他隊(duì)列無(wú)效

dispatch_set_target_queue 前面提到過(guò),我們自己創(chuàng)建的隊(duì)列的優(yōu)先級(jí)是默認(rèn)優(yōu)先級(jí)骇吭,需要更改優(yōu)先級(jí)需要調(diào)用dispatch_set_target_queue(系統(tǒng)的隊(duì)列優(yōu)先級(jí)不能修改)绵跷。實(shí)際上碾局,dispatch_set_target_queue 主要有兩個(gè)作用:
(1)更改 dispatch_queue_create 函數(shù)創(chuàng)建的隊(duì)列的優(yōu)先級(jí)净当。代碼如下:

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(queue, dispatch_get_global_queue(0, 0));

函數(shù)中第一個(gè)是需要變更優(yōu)先級(jí)的隊(duì)列像啼,第二個(gè)參數(shù)是需要傳入全局并發(fā)隊(duì)列忽冻,并且優(yōu)先級(jí)是第一個(gè)參數(shù)想要的優(yōu)先級(jí)。
(2)修改用戶隊(duì)列的目標(biāo)隊(duì)列湖笨,使多個(gè)serial queue在目標(biāo)queue上一次只有一個(gè)執(zhí)行慈省。第二個(gè)參數(shù)是目標(biāo)隊(duì)列边败,第一個(gè)參數(shù)是任務(wù)將放在目標(biāo)隊(duì)列中的另一串行隊(duì)列致燥。
例如,用戶要依次下載小說(shuō)A匾寝、B艳悔、C,但下載任務(wù)放在不同的串行隊(duì)列中乔外,這時(shí)就可以依次調(diào)用dispatch_set_target_queue杨幼,將放有下載任務(wù)的隊(duì)列作為第一個(gè)參數(shù)傳入差购,讓任務(wù)將目標(biāo)隊(duì)列中同步執(zhí)行欲逃。 示例代碼如下:

dispatch_queue_t targetQueue = dispatch_queue_create("targetQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue3 = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(queue1, targetQueue);
    dispatch_set_target_queue(queue2, targetQueue);
    dispatch_set_target_queue(queue3, targetQueue);
    dispatch_async(queue1, ^{
        NSLog(@"開(kāi)始下載小說(shuō)A");
        /*
         下載中
         */
        NSLog(@"小說(shuō)A下載完成");
    });
    dispatch_async(queue2, ^{
        NSLog(@"開(kāi)始下載小說(shuō)B");
        /*
         下載中
         */
        NSLog(@"小說(shuō)B下載完成");
    });
    dispatch_async(queue3, ^{
        NSLog(@"開(kāi)始下載小說(shuō)C");
        /*
         下載中
         */
        NSLog(@"小說(shuō)C下載完成");
    });
運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迈着,一起剝皮案震驚了整個(gè)濱河市裕菠,隨后出現(xiàn)的幾起案子奴潘,更是在濱河造成了極大的恐慌掘剪,老刑警劉巖夺谁,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碉纳,死亡現(xiàn)場(chǎng)離奇詭異劳曹,居然都是意外死亡铁孵,警方通過(guò)查閱死者的電腦和手機(jī)账忘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人期升,你說(shuō)我怎么就攤上這事播赁∪菸” “怎么了替劈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我龄捡,道長(zhǎng)命黔,這世上最難降的妖魔是什么悍募? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任喜鼓,我火速辦了婚禮庄岖,結(jié)果婚禮上心剥,老公的妹妹穿的比我還像新娘优烧。我一直安慰自己,他們只是感情好捍掺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布喂柒。 她就那樣靜靜地躺著蚊丐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天霎终,我揣著相機(jī)與錄音莱褒,去河邊找鬼沛励。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的徒河。 我是一名探鬼主播送漠,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼顽照,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了闽寡?” 一聲冷哼從身側(cè)響起代兵,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爷狈,沒(méi)想到半個(gè)月后植影,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涎永,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年思币,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羡微。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谷饿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拷淘,到底是詐尸還是另有隱情各墨,我是刑警寧澤指孤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布启涯,位于F島的核電站,受9級(jí)特大地震影響恃轩,放射性物質(zhì)發(fā)生泄漏结洼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一叉跛、第九天 我趴在偏房一處隱蔽的房頂上張望松忍。 院中可真熱鬧,春花似錦筷厘、人聲如沸鸣峭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)摊溶。三九已至,卻和暖如春充石,著一層夾襖步出監(jiān)牢的瞬間莫换,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拉岁,地道東北人坷剧。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像喊暖,于是被迫代替她去往敵國(guó)和親惫企。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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

  • GCD (Grand Central Dispatch) :iOS4 開(kāi)始引入陵叽,使用更加方便雅任,程序員只需要將任務(wù)添...
    池鵬程閱讀 1,332評(píng)論 0 2
  • 從哪說(shuō)起呢? 單純講多線程編程真的不知道從哪下嘴咨跌。沪么。 不如我直接引用一個(gè)最簡(jiǎn)單的問(wèn)題,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,757評(píng)論 1 17
  • 一殉摔、多線程簡(jiǎn)介: 所謂多線程是指一個(gè) 進(jìn)程 -- process(可以理解為系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序)中可以開(kāi)...
    尋形覓影閱讀 1,030評(píng)論 0 6
  • 最近頗花了一番功夫把多線程GCD人的一些用法總結(jié)出來(lái),一來(lái)幫自己鞏固一下知識(shí)记焊、二來(lái)希望能幫到對(duì)這一塊還迷茫...
    人活一世閱讀 289評(píng)論 1 1
  • 你為什么要這么對(duì)我?我就想問(wèn)問(wèn)你瓢颅,為什么這么對(duì)我恩尾?談戀愛(ài)5年了,我對(duì)你怎么樣你心里清楚挽懦,一直以來(lái)翰意,我都對(duì)你這么好,...
    小月亮芽?jī)?/span>閱讀 263評(píng)論 2 1