關(guān)于GCD總結(jié)

什么是GCD

Grand Central Dispatch或者GCD,是一套低層API,提供了一種新的方法來進(jìn)行并發(fā)程序編寫。他們都允許程序?qū)⑷蝿?wù)切分為多個(gè)單一任務(wù)然后提交至工作隊(duì)列來并發(fā)地或者串行地執(zhí)行。GCD比之NSOpertionQueue更底層更高效回铛,并且它不是Cocoa框架的一部分。

除了代碼的平行執(zhí)行能力克锣,GCD還提供高度集成的事件控制系統(tǒng)茵肃。可以設(shè)置句柄來響應(yīng)文件描述符袭祟、mach ports(Mach port 用于 OS X上的進(jìn)程間通訊)验残、進(jìn)程、計(jì)時(shí)器巾乳、信號(hào)您没、用戶生成事件。這些句柄通過GCD來并發(fā)執(zhí)行胆绊。

GCD的API很大程度上基于block氨鹏,當(dāng)然,GCD也可以脫離block來使用压状,比如使用傳統(tǒng)c機(jī)制提供函數(shù)指針和上下文指針仆抵。實(shí)踐證明,當(dāng)配合block使用時(shí)种冬,GCD非常簡(jiǎn)單易用且能發(fā)揮其最大能力镣丑。

理解串行、并發(fā)及同步異步

串行和并發(fā)

串行和并發(fā)描述了任務(wù)之間執(zhí)行的時(shí)機(jī)碌廓。任務(wù)如果是串行的传轰,那么在同一時(shí)間只執(zhí)行一個(gè)任務(wù)。并發(fā)的多個(gè)任務(wù)被執(zhí)行的時(shí)候谷婆,可能是在同一時(shí)間。

同步和異步

同步和異步描述了一個(gè)函數(shù)相對(duì)于另一個(gè)函數(shù)何時(shí)執(zhí)行完畢辽聊。同步的函數(shù)只有當(dāng)它調(diào)用的任務(wù)執(zhí)行完纪挎,才會(huì)返回。而異步函數(shù)跟匆,會(huì)立即返回异袄。雖然它也命令任務(wù)執(zhí)行完,但它并不等待任務(wù)執(zhí)行完玛臂。如此烤蜕,異步函數(shù)就不會(huì)阻塞當(dāng)前線程封孙。(這樣說可能有些過于抽象了,個(gè)人理解的是讽营,在同步的時(shí)候沒有開啟子線程的能力虎忌,而在異步的時(shí)候具備開啟子線程的能力)。

隊(duì)列

串行隊(duì)列

1)使用dispatch_queue_create函數(shù)創(chuàng)建串行隊(duì)列
dispatch_queue_t queue  = dispatch_queue_create(“隊(duì)列名”橱鹏,NULL);
dispatch_queue_t queue  = dispatch_queue_create(“隊(duì)列名”膜蠢,DISPATCH_QUEUE_SERIAL);

兩者等效.
2)使用主隊(duì)列(在主隊(duì)列中的任務(wù),都會(huì)放到主線程中執(zhí)行莉兰,它也是唯一一個(gè)允許更新UI的隊(duì)列挑围,所以要是開啟子線程的時(shí)候要更新UI的情況下一定要用主隊(duì)列進(jìn)行更新)

dispatch_queue_t queue = dispatch_get_main_queue();

并發(fā)隊(duì)列(GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊(duì)列)

1)獲得全局隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(dispatch_queue_priority,unsigned long flags);
        前一個(gè)參數(shù)是優(yōu)先級(jí)糖荒,有以下幾種:
        DISPATCH_QUEUE_PRIORITY_HIGH 2//高
        DISPATCH_QUEUE_PRIORITY_DEFAULT 0//默認(rèn)
        DISPATCH_QUEUE_PRIORITY_LOW (-2)//低
        DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MN//后臺(tái)
2)自定義并發(fā)隊(duì)列
dispatch_queue_t queue  = dispatch_queue_create(“隊(duì)列名”杉辙,DISPATCH_QUEUE_CONCURRENT);
在開發(fā)中基本上就是通過dispatch_async和dispatch_sync 分別配合著上面的三種隊(duì)列使用,但是更多的情況下基本上就是dispatch_async和全局隊(duì)列配合使用捶朵,并用主線程中更新UI奏瞬。

dispatch_async

1)全局隊(duì)列
    //在這里獲取全局隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"task2%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"task3%@",[NSThread currentThread]);
    });

打印結(jié)果

2016-07-31 21:08:51.114 GCD[81282:8816505] task2<NSThread: 0x7fb36b900080>{number = 2, name = (null)}
2016-07-31 21:08:51.114 GCD[81282:8816516] task3<NSThread: 0x7fb369ff59a0>{number = 3, name = (null)}
2016-07-31 21:08:51.114 GCD[81282:8816512] task1<NSThread: 0x7fb369e2bba0>{number = 4, name = (null)}
可以看出GCD開啟了子線程并且并發(fā)執(zhí)行
2)主隊(duì)列
    //在這里獲取主隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"task2%@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"task3%@",[NSThread currentThread]);
    });

打印結(jié)果

2016-07-31 21:14:37.452 GCD[81293:8820034] task1<NSThread: 0x7ffb7a000720>{number = 1, name = main}
2016-07-31 21:14:37.452 GCD[81293:8820034] task2<NSThread: 0x7ffb7a000720>{number = 1, name = main}
2016-07-31 21:14:37.452 GCD[81293:8820034] task3<NSThread: 0x7ffb7a000720>{number = 1, name = main}
可以看出來雖然用了dispatch_async但是并沒有開啟子線程來執(zhí)行任務(wù),這是因?yàn)殛?duì)列的性質(zhì)決定的泉孩,所以在用主隊(duì)列的時(shí)候要注意硼端。

dispatch_sync

1)全局隊(duì)列
    //在這里獲取全局隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_sync(queue, ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"task2%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"task3%@",[NSThread currentThread]);
    });

打印結(jié)果

2016-07-31 21:19:06.993 GCD[81311:8822954] task1<NSThread: 0x7f9208e04fe0>{number = 1, name = main}
2016-07-31 21:19:06.994 GCD[81311:8822954] task2<NSThread: 0x7f9208e04fe0>{number = 1, name = main}
2016-07-31 21:19:06.994 GCD[81311:8822954] task3<NSThread: 0x7f9208e04fe0>{number = 1, name = main}
可以看出來dispatch_sync中雖然用的是全局隊(duì)列,但是并沒有并發(fā)寓搬,因?yàn)閐ispatch_sync沒有開啟子線程的能力珍昨,只能在主線程中串行執(zhí)行任務(wù)。
2)主隊(duì)列
    //在這里獲取主隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"task2%@",[NSThread currentThread]);
    });
    dispatch_sync(queue, ^{
        NSLog(@"task3%@",[NSThread currentThread]);
    });
這樣是不會(huì)有打印結(jié)果的句喷,因?yàn)榘l(fā)生了死鎖镣典,在這個(gè)過程中,主線等著GCD運(yùn)行完成后繼續(xù)運(yùn)行而GCD等待著主線運(yùn)行完成后繼續(xù)運(yùn)行唾琼,產(chǎn)生了死鎖兄春,所以不能這樣使用。

dispatch_after

  //在這里只有用主隊(duì)列有意義
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    NSLog(@"主線");

打印結(jié)果

2016-07-31 21:37:14.292 GCD[81346:8829855] 主線
2016-07-31 21:37:17.292 GCD[81346:8829855] task1<NSThread: 0x7fee08604ea0>{number = 1, name = main}
可以看出在block中的任務(wù)被延遲了3秒鐘執(zhí)行锡溯。但是這個(gè)是有問題的赶舆,這里只是延時(shí)提交了block,并不是延時(shí)后立即執(zhí)行祭饭。所以dispatch_after不能精準(zhǔn)的控制運(yùn)行狀態(tài)芜茵。

dispatch_once

dispatch_once是一種線程安全的方式,執(zhí)行只執(zhí)行一次代碼塊保證多線程安全倡蝙。
   + (instancetype)sharedManager
    {
        static ToolManager *sharedPhotoManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedManager = [[ToolManager alloc] init];
        });
        return sharedPhotoManager;
    }

dispatch_group

有的時(shí)候我們要在完成一些任務(wù)的前提下再去完成后面的任務(wù)九串,這個(gè)時(shí)候就要用到dispatch_group。
1)同步的方式(dispatch_group_wait)(這個(gè)方法會(huì)阻塞線程,后面的代碼要等到wait完成后運(yùn)行)
    //由于我們用了同步的方式dispatch_group_wait猪钮,它會(huì)阻塞當(dāng)前線程品山,所以我們?cè)谡麄€(gè)方法外面套上了dispatch_async,使它在后臺(tái)執(zhí)行而不會(huì)阻塞主線程烤低。
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        dispatch_group_t downloadGroup = dispatch_group_create();
        
        for (NSInteger i = 0; i < 3; i++) {
            //dispatch_group_enter告知group肘交,一個(gè)任務(wù)開始了。我們需要將dispatch_group_enter與dispatch_group_leave配對(duì)拂玻,否則我們會(huì)遇到莫名其妙的崩潰酸些。
            dispatch_group_enter(downloadGroup);
            
            sleep(2);
            NSLog(@"task%ld",i);
            //dispatch_group_leave告知group,此任務(wù)執(zhí)行完畢檐蚜,要注意與dispatch_group_enter配對(duì)魄懂。
            dispatch_group_leave(downloadGroup);
            
        }
        //dispatch_group_wait等待所有任務(wù)完成或者超時(shí),在此處我們?cè)O(shè)置等待時(shí)間為永遠(yuǎn)DISPATCH_TIME_FOREVER
        dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER);
        //當(dāng)以上所有任務(wù)執(zhí)行完后闯第,我們?cè)谥麝?duì)列調(diào)用任務(wù)完成的block市栗。
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"主線");
        });
    });
在這里有個(gè)問題,就是說如果我們將其中的超時(shí)時(shí)間設(shè)置成5秒咳短,但是其中的一個(gè)任務(wù)要延時(shí)10秒填帽,那么這個(gè)任務(wù)不會(huì)因?yàn)檫@個(gè)超時(shí)時(shí)間到了停止,還會(huì)繼續(xù)完成任務(wù)咙好,但是不會(huì)等到這個(gè)任務(wù)完成后再去執(zhí)行dispatch_group_wait后面的代碼篡腌。

2)異步的方式(dispatch_group_notify)(不會(huì)阻塞線程,后面的代碼會(huì)執(zhí)行勾效,不用等待這些任務(wù)和notify)
    dispatch_group_t downloadGroup = dispatch_group_create();
    
    dispatch_group_async(downloadGroup, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"task1%@",[NSThread currentThread]);
    });
    dispatch_group_async(downloadGroup, dispatch_get_global_queue(0, 0), ^{
         NSLog(@"task2%@",[NSThread currentThread]);
    });
    dispatch_group_async(downloadGroup, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"task3%@",[NSThread currentThread]);
    });
    dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
        NSLog(@"主線");
    });

其中還涉及到了dispatch_group_enter和dispatch_group_leave嘹悼,我理解這個(gè)就是將任務(wù)添加到隊(duì)列中,并且他們要成對(duì)的出現(xiàn)层宫。他們將任務(wù)添加到當(dāng)前的線程中杨伙,也就是說如果任務(wù)都沒有開啟子線程,那么添加進(jìn)去的就是在當(dāng)前的線程中串行執(zhí)行萌腿,如果任務(wù)開啟了子線程限匣,那么添加進(jìn)去的就是在相對(duì)的子線程可能串行,可能并行(這個(gè)要看隊(duì)列的性質(zhì))

    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        dispatch_group_leave(group);
    });

  dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        
    });
這兩種的性質(zhì)是一樣的毁菱。

dispatch_apply

dispatch_apply(3, dispatch_get_global_queue(0, 0), ^(size_t i) {
        sleep(2);
        NSLog(@"任務(wù)組%d完成%@",i,[NSThread currentThread]);
    });

打印結(jié)果

2016-07-31 23:54:15.378 GCD[81633:8885238] 任務(wù)組0完成<NSThread: 0x7fbaf3704c10>{number = 1, name = main}
2016-07-31 23:54:15.381 GCD[81633:8885283] 任務(wù)組2完成<NSThread: 0x7fbaf3623960>{number = 2, name = (null)}
2016-07-31 23:54:15.381 GCD[81633:8885275] 任務(wù)組1完成<NSThread: 0x7fbaf3526f50>{number = 3, name = (null)}
dispatch_apply和for循環(huán)都是串行的米死,當(dāng)dispatch_apply中的工作全都完成后才會(huì)返回,可以看出來里面的是并發(fā)執(zhí)行的所以返回的先后順序是不能確定的鼎俘,不能和for循環(huán)一樣用哲身。

dispatch_suspend和dispatch_resume

 dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);
    //提交第一個(gè)block,延時(shí)5秒打印贸伐。
    dispatch_async(queue, ^{
        
        [NSThread sleepForTimeInterval:5];
        
        NSLog(@"After 5 seconds...");
    });
    //提交第二個(gè)block,也是延時(shí)5秒打印
    dispatch_async(queue, ^{
        
        [NSThread sleepForTimeInterval:5];
        
        NSLog(@"After 5 seconds again...");
    });
    //延時(shí)一秒
    
    NSLog(@"sleep 1 second...");
    [NSThread sleepForTimeInterval:1];
    //掛起隊(duì)列
    
    NSLog(@"suspend...");
    dispatch_suspend(queue);
    //延時(shí)10秒
    
    NSLog(@"sleep 10 second...");
    [NSThread sleepForTimeInterval:10];
    //恢復(fù)隊(duì)列
    dispatch_resume(queue);
    
    NSLog(@"resume...");

打印結(jié)果

2016-08-01 13:46:29.817 GCD[81925:8937362] sleep 1 second...
2016-08-01 13:46:30.818 GCD[81925:8937362] suspend...
2016-08-01 13:46:30.819 GCD[81925:8937362] sleep 10 second...
2016-08-01 13:46:34.819 GCD[81925:8937412] After 5 seconds...
2016-08-01 13:46:40.819 GCD[81925:8937362] resume...
2016-08-01 13:46:45.820 GCD[81925:8937412] After 5 seconds again...
這兩個(gè)就是將任務(wù)掛起和恢復(fù)的功能怔揩,從結(jié)果可以看出來當(dāng)隊(duì)列掛起后第一個(gè)block還是在運(yùn)行捉邢,并且能夠正常的輸出脯丝。可知伏伐,dispatch_suspend并不會(huì)停止正在運(yùn)行的block宠进,只會(huì)暫停后續(xù)的block的執(zhí)行。

dispatch_barrier_async和dispatch_barrier_sync

dispatch_queue_t queue = dispatch_queue_create("msdf",  DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"task1");
    });
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"task2");
    });
    dispatch_barrier_async(queue, ^{
        sleep(3);
        NSLog(@"barrier");
    });
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"task3");
    });
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"task4");
    });
dispatch_barrier_async的作用就是向某個(gè)隊(duì)列插入一個(gè)block藐翎,當(dāng)目前正在執(zhí)行的block運(yùn)行完成后材蹬,阻塞這個(gè)block后面添加的block,只運(yùn)行這個(gè)block直到完成吝镣,然后再繼續(xù)后續(xù)的任務(wù)堤器。
dispatch_barrier\(a)sync只在自己創(chuàng)建的并發(fā)隊(duì)列上有效,在全局(Global)并發(fā)隊(duì)列末贾、串行隊(duì)列上闸溃,效果跟dispatch_(a)sync效果一樣。
接下來就來看看dispatch_barrier_sync和dispatch_barrier_async的相同點(diǎn)與不同點(diǎn)
相同點(diǎn):兩者只有前面的任務(wù)執(zhí)行完成之后并且執(zhí)行完成barrier中的代碼后才能執(zhí)行后面的任務(wù)拱撵。
            兩者都能夠阻塞當(dāng)前的線程
不同點(diǎn):dispatch_barrier_async在阻塞當(dāng)前線程時(shí)辉川,不需要等待barrier中的代碼完成后再運(yùn)行后面的非任務(wù)代碼;
         dispatch_barrier_sync在阻塞當(dāng)前線程時(shí)拴测,需要等待barrier中的代碼完成后再運(yùn)行后面的非任務(wù)代碼乓旗。

dispatch_semaphore

信號(hào)量是一個(gè)整形值并且具有一個(gè)初始計(jì)數(shù)值,并且支持兩個(gè)操作:信號(hào)通知和等待集索。當(dāng)一個(gè)信號(hào)量被信號(hào)通知屿愚,其計(jì)數(shù)會(huì)被增加。當(dāng)一個(gè)線程在一個(gè)信號(hào)量上等待時(shí)抄谐,線程會(huì)被阻塞(如果有必要的話)渺鹦,直至計(jì)數(shù)器大于零,然后線程會(huì)減少這個(gè)計(jì)數(shù)蛹含。

在GCD中有三個(gè)函數(shù)是semaphore的操作毅厚,分別是:
  dispatch_semaphore_create   創(chuàng)建一個(gè)semaphore
  dispatch_semaphore_signal   發(fā)送一個(gè)信號(hào)
  dispatch_semaphore_wait    等待信號(hào)
  簡(jiǎn)單的介紹一下這三個(gè)函數(shù),第一個(gè)函數(shù)有一個(gè)整形的參數(shù)浦箱,我們可以理解為信號(hào)的總量吸耿,dispatch_semaphore_signal是發(fā)送一個(gè)信號(hào),自然會(huì)讓信號(hào)總量加1酷窥,dispatch_semaphore_wait等待信號(hào)咽安,當(dāng)信號(hào)總量少于0的時(shí)候就會(huì)一直等待,否則就可以正常的執(zhí)行蓬推,并讓信號(hào)總量-1妆棒,根據(jù)這樣的原理,我們便可以快速的創(chuàng)建一個(gè)并發(fā)控制來同步任務(wù)和有限資源訪問控制。

    dispatch_group_t group = dispatch_group_create();   
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);   
    for (int i = 0; i < 100; i++)   
    {   
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);   
        dispatch_group_async(group, queue, ^{   
            NSLog(@"%i",i);   
            sleep(2);   
            dispatch_semaphore_signal(semaphore);   
        });   
    }   
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
簡(jiǎn)單的介紹一下這一段代碼糕珊,創(chuàng)建了一個(gè)初使值為10的semaphore动分,每一次for循環(huán)都會(huì)創(chuàng)建一個(gè)新的線程,線程結(jié)束的時(shí)候會(huì)發(fā)送一個(gè)信號(hào)红选,線程創(chuàng)建之前會(huì)信號(hào)等待澜公,所以當(dāng)同時(shí)創(chuàng)建了10個(gè)線程之后,for循環(huán)就會(huì)阻塞喇肋,等待有線程結(jié)束之后會(huì)增加一個(gè)信號(hào)才繼續(xù)執(zhí)行坟乾,如此就形成了對(duì)并發(fā)的控制,如上就是一個(gè)并發(fā)數(shù)為10的一個(gè)線程隊(duì)列蝶防。

dispatch_get_current_queue

現(xiàn)在這個(gè)方法已經(jīng)被不建議使用了甚侣,但是就像在此強(qiáng)調(diào)一下,這個(gè)方法用不好會(huì)造成死鎖慧脱,在此不再贅余渺绒。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市菱鸥,隨后出現(xiàn)的幾起案子宗兼,更是在濱河造成了極大的恐慌,老刑警劉巖氮采,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殷绍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鹊漠,警方通過查閱死者的電腦和手機(jī)主到,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躯概,“玉大人登钥,你說我怎么就攤上這事∪⒚遥” “怎么了牧牢?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)姿锭。 經(jīng)常有香客問我塔鳍,道長(zhǎng),這世上最難降的妖魔是什么呻此? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任轮纫,我火速辦了婚禮,結(jié)果婚禮上焚鲜,老公的妹妹穿的比我還像新娘掌唾。我一直安慰自己放前,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布郑兴。 她就那樣靜靜地躺著犀斋,像睡著了一般贝乎。 火紅的嫁衣襯著肌膚如雪情连。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天览效,我揣著相機(jī)與錄音却舀,去河邊找鬼。 笑死锤灿,一個(gè)胖子當(dāng)著我的面吹牛挽拔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播但校,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼螃诅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了状囱?” 一聲冷哼從身側(cè)響起术裸,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亭枷,沒想到半個(gè)月后寞埠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冒萄,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了患朱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昧识,死狀恐怖疮丛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驴党,我是刑警寧澤瘪撇,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站鼻弧,受9級(jí)特大地震影響设江,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攘轩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一叉存、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧度帮,春花似錦歼捏、人聲如沸稿存。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓣履。三九已至,卻和暖如春练俐,著一層夾襖步出監(jiān)牢的瞬間袖迎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工腺晾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燕锥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓悯蝉,卻偏偏與公主長(zhǎng)得像归形,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鼻由,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

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