iOS底層原理:GCD的函數(shù)與隊(duì)列

GCD

簡介

  • GCD全稱是Grand Central Dispatch
  • 純C語言孩革,提供例如非常強(qiáng)大的函數(shù)

優(yōu)勢

  • GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案
  • GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核(比如雙核逆趣、四核)
  • GCD會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程苹支、調(diào)度任務(wù)、銷毀線程)
  • 程序員只需要告訴GCD想要執(zhí)行什么任務(wù)俱济,不需要編寫任何線程管理代碼

【重點(diǎn)】用一句話總結(jié)GCD就是:將任務(wù)添加到隊(duì)列嘶是,并指定任務(wù)執(zhí)行的函數(shù)

核心

在日常開發(fā)中,GCD一般寫成下面這種形式

 dispatch_async( dispatch_queue_create("com.sunrise.queue", NULL), ^{
   NSLog(@"GCD基本使用");
});

將上述代碼拆分姨蝴,方便我們來理解GCD核心 主要是由 任務(wù) + 隊(duì)列 + 函數(shù) 構(gòu)成

//********GCD基礎(chǔ)寫法********
//創(chuàng)建任務(wù)
dispatch_block_t block = ^{
    NSLog(@"hello GCD");
};

//創(chuàng)建串行隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("com.sunrise.queue", NULL);

//將任務(wù)添加到隊(duì)列,并指定函數(shù)執(zhí)行
dispatch_async(queue, block);
  • 使用dispatch_block_t創(chuàng)建任務(wù)
  • 使用dispatch_queue_t創(chuàng)建隊(duì)列
  • 任務(wù)添加到隊(duì)列肺缕,并指定執(zhí)行任務(wù)的函數(shù)dispatch_async
注意

這里的任務(wù)是指執(zhí)行操作的意思左医,在使用dispatch_block_t創(chuàng)建任務(wù)時(shí),主要有以下兩點(diǎn)說明

  • 任務(wù)使用block封裝
  • 任務(wù)的block沒有參數(shù)沒有返回值

函數(shù)與隊(duì)列

函數(shù)

在GCD中執(zhí)行任務(wù)的方式有兩種同木,同步執(zhí)行異步執(zhí)行浮梢,分別對(duì)應(yīng) 同步函數(shù)dispatch_sync異步函數(shù)dispatch_async,兩者對(duì)比如下

  • 同步執(zhí)行彤路,對(duì)應(yīng)同步函數(shù)dispatch_sync

    • 必須等待當(dāng)前語句執(zhí)行完畢秕硝,才會(huì)執(zhí)行下一條語句
    • 不會(huì)開啟線程,即不具備開啟新線程的能力
    • 在當(dāng)前線程中執(zhí)行block任務(wù)
  • 異步執(zhí)行洲尊,對(duì)應(yīng)異步函數(shù)dispatch_async

    • 不用等待當(dāng)前語句執(zhí)行完畢远豺,就可以執(zhí)行下一條語句
    • 會(huì)開啟線程執(zhí)行block任務(wù),即具備開啟新線程的能力(但并不一定開啟新線程坞嘀,這個(gè)與任務(wù)所指定的隊(duì)列類型有關(guān))
    • 異步多線程 的代名詞

所以躯护,綜上所述,兩種執(zhí)行方式的主要區(qū)別有兩點(diǎn):

  • 是否等待隊(duì)列的任務(wù)執(zhí)行完畢
  • 是否具備開啟新線程的能力

隊(duì)列

串行隊(duì)列 和 并發(fā)隊(duì)列

多線程中所說的隊(duì)列(Dispatch Queue)是指執(zhí)行任務(wù)的等待隊(duì)列丽涩,即用來存放任務(wù)的隊(duì)列棺滞。隊(duì)列是一種特殊的線性表,遵循先進(jìn)先出(FIFO)原則矢渊,即新任務(wù)總是被插入到隊(duì)尾继准,而任務(wù)的讀取從隊(duì)首開始讀取。每讀取一個(gè)任務(wù)矮男,則動(dòng)隊(duì)列中釋放一個(gè)任務(wù)移必,如下圖所示

隊(duì)列

在GCD中,隊(duì)列主要分為串行隊(duì)列(Serial Dispatch Queue)并發(fā)隊(duì)列(Concurrent Dispatch Queue)兩種毡鉴,如下圖所示

串行與并發(fā)
  • 串行隊(duì)列:每次只有一個(gè)任務(wù)被執(zhí)行避凝,等待上一個(gè)任務(wù)執(zhí)行完畢再執(zhí)行下一個(gè)舞萄,即只開啟一個(gè)線程(通俗理解:同一時(shí)刻只調(diào)度一個(gè)任務(wù)執(zhí)行)
    • 使用dispatch_queue_create("xxx", DISPATCH_QUEUE_SERIAL);創(chuàng)建串行隊(duì)列
    • 其中的DISPATCH_QUEUE_SERIAL也可以使用NULL表示,這兩種均表示 默認(rèn)的串行隊(duì)列
// 串行隊(duì)列的獲取方法
dispatch_queue_t serialQueue1 = dispatch_queue_create("com.sunrise.queue", NULL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("com.sunrise.queue", DISPATCH_QUEUE_SERIAL);
  • 并發(fā)隊(duì)列:一次可以并發(fā)執(zhí)行多個(gè)任務(wù)管削,即開啟多個(gè)線程倒脓,并同時(shí)執(zhí)行任務(wù)(通俗理解:同一時(shí)刻可以調(diào)度多個(gè)任務(wù)執(zhí)行)
    • 使用dispatch_queue_create("xxx", DISPATCH_QUEUE_CONCURRENT);創(chuàng)建并發(fā)隊(duì)列
    • 注意:并發(fā)隊(duì)列的并發(fā)功能只有在異步函數(shù)下才有效
// 并發(fā)隊(duì)列的獲取方法
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.sunrise.queue", DISPATCH_QUEUE_CONCURRENT);

主隊(duì)列 和 全局并發(fā)隊(duì)列

在GCD中,針對(duì)這兩種隊(duì)列含思,分別提供了主隊(duì)列(Main Dispatch Queue)全局并發(fā)隊(duì)列(Global Dispatch Queue)

  • 主隊(duì)列(Main Dispatch Queue):GCD中提供的特殊的串行隊(duì)列
    • 專門用來 在主線程上調(diào)度任務(wù)的串行隊(duì)列崎弃,依賴于主線程、主Runloop含潘,在main函數(shù)調(diào)用之前自動(dòng)創(chuàng)建
    • 不會(huì)開啟線程
    • 如果當(dāng)前主線程正在有任務(wù)執(zhí)行饲做,那么無論主隊(duì)列中當(dāng)前被添加了什么任務(wù),都不會(huì)被調(diào)度
    • 使用dispatch_get_main_queue()獲得主隊(duì)列
    • 通常在返回主線程更新UI時(shí)使用
//主隊(duì)列的獲取方法
dispatch_queue_t mainQueue = dispatch_get_main_queue();
  • 全局并發(fā)隊(duì)列(Global Dispatch Queue):GCD提供的默認(rèn)的并發(fā)隊(duì)列
    • 為了方便程序員的使用遏弱,蘋果提供了全局隊(duì)列
    • 在使用多線程開發(fā)時(shí)盆均,如果對(duì)隊(duì)列沒有特殊需求,在執(zhí)行異步任務(wù)時(shí)漱逸,可以直接使用全局隊(duì)列
    • 使用dispatch_get_global_queue獲取全局并發(fā)隊(duì)列泪姨,最簡單的是dispatch_get_global_queue(0, 0)
      • 第一個(gè)參數(shù)表示隊(duì)列優(yōu)先級(jí),默認(rèn)優(yōu)先級(jí)為DISPATCH_QUEUE_PRIORITY_DEFAULT=0饰抒,在iOS9之后肮砾,已經(jīng)被服務(wù)質(zhì)量(quality-of-service)取代
      • 第二個(gè)參數(shù)使用0
//全局并發(fā)隊(duì)列的獲取方法
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);

//優(yōu)先級(jí)從高到低(對(duì)應(yīng)的服務(wù)質(zhì)量)依次為
- DISPATCH_QUEUE_PRIORITY_HIGH       -- QOS_CLASS_USER_INITIATED
- DISPATCH_QUEUE_PRIORITY_DEFAULT    -- QOS_CLASS_DEFAULT
- DISPATCH_QUEUE_PRIORITY_LOW        -- QOS_CLASS_UTILITY
- DISPATCH_QUEUE_PRIORITY_BACKGROUND -- QOS_CLASS_BACKGROUND
全局并發(fā)隊(duì)列 + 主隊(duì)列 配合使用

在日常開發(fā)中,全局隊(duì)列+并發(fā)并列一般是這樣配合使用的

//主隊(duì)列 + 全局并發(fā)隊(duì)列的日常使用
dispatch_async(dispatch_get_global_queue(0, 0), ^{
  //執(zhí)行耗時(shí)操作
  dispatch_async(dispatch_get_main_queue(), ^{
     //回到主線程進(jìn)行UI操作
  });      
});

函數(shù)與隊(duì)列的不同組合

串行隊(duì)列 + 同步函數(shù)

【任務(wù)按順序執(zhí)行】:任務(wù)一個(gè)接一個(gè)的在當(dāng)前線程執(zhí)行袋坑,不開辟新線程

串行隊(duì)列 + 異步函數(shù)

【任務(wù)按順序執(zhí)行】:任務(wù)一個(gè)接一個(gè)的執(zhí)行仗处,會(huì)開辟新線程

并發(fā)隊(duì)列 + 同步函數(shù)

【任務(wù)按順序執(zhí)行】:任務(wù)一個(gè)接一個(gè)的執(zhí)行,不開辟線程

并發(fā)隊(duì)列 + 異步函數(shù)

【任務(wù)按亂序執(zhí)行】:任務(wù)執(zhí)行無順序枣宫,會(huì)開辟新線程

主隊(duì)列 + 同步函數(shù)

【造成死鎖】:任務(wù)相互等待婆誓,造成死鎖

造成死鎖的原因分析如下:

  • 主隊(duì)列有兩個(gè)任務(wù),順序?yàn)椋?NSLog任務(wù) - 同步block
  • 執(zhí)行NSLog任務(wù)后也颤,執(zhí)行同步Block旷档,會(huì)將任務(wù)1(即i=1時(shí))加入到主隊(duì)列,主隊(duì)列順序?yàn)椋?code>NSLog任務(wù) - 同步block - 任務(wù)1
  • 任務(wù)1的執(zhí)行需要等待同步block執(zhí)行完畢才會(huì)執(zhí)行歇拆,而同步block的執(zhí)行需要等待任務(wù)1執(zhí)行完畢鞋屈,所以就造成了任務(wù)互相等待的情況,即造成死鎖崩潰
死鎖現(xiàn)象
  • 主線程因?yàn)?code>同步函數(shù)的原因等著先執(zhí)行任務(wù)
  • 主隊(duì)列等著主線程的任務(wù)執(zhí)行完畢再執(zhí)行自己的任務(wù)
  • 主隊(duì)列和主線程相互等待會(huì)造成死鎖

主隊(duì)列 + 異步函數(shù)

【任務(wù)按順序執(zhí)行】:任務(wù)一個(gè)接一個(gè)的執(zhí)行故觅,不開辟線程

全局并發(fā)隊(duì)列 + 同步函數(shù)

【任務(wù)按順序執(zhí)行】:任務(wù)一個(gè)接一個(gè)的執(zhí)行厂庇,不開辟新線程

全局并發(fā)隊(duì)列 + 異步函數(shù)

【任務(wù)按亂序執(zhí)行】:任務(wù)亂序執(zhí)行,會(huì)開辟新線程

總結(jié)

函數(shù)隊(duì)列 串行隊(duì)列 并發(fā)隊(duì)列 主隊(duì)列 全局并發(fā)隊(duì)列
同步函數(shù) 順序執(zhí)行输吏,不開辟線程 順序執(zhí)行权旷,不開辟線程 死鎖 順序執(zhí)行,不開辟線程
異步函數(shù) 順序執(zhí)行,開辟線程 亂序執(zhí)行拄氯,開辟線程 順序執(zhí)行躲查,不開辟線程 亂序執(zhí)行,開辟線程

相關(guān)面試題解析

【面試題 - 1】異步函數(shù)+并行隊(duì)列

下面代碼的輸出順序是什么译柏?

- (void)interview01{
    //并行隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("com.CJL.Queue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    // 耗時(shí)
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_async(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}
----------打印結(jié)果-----------
輸出順序?yàn)椋? 5 2 4 3
  • 異步函數(shù)不會(huì)阻塞主隊(duì)列镣煮,會(huì)開辟新線程執(zhí)行異步任務(wù)
代碼分析

如下圖所示,紅線表示任務(wù)的執(zhí)行順序

  • 主線程的任務(wù)隊(duì)列為:任務(wù)1鄙麦、異步block1典唇、任務(wù)5,其中異步block1會(huì)比較耗費(fèi)性能胯府,任務(wù)1和任務(wù)5的任務(wù)復(fù)雜度是相同的介衔,所以任務(wù)1和任務(wù)5優(yōu)先于異步block1執(zhí)行

  • 異步block1中,任務(wù)隊(duì)列為:任務(wù)2骂因、異步block2炎咖、任務(wù)4,其中block2相對(duì)比較耗費(fèi)性能寒波,任務(wù)2任務(wù)4是復(fù)雜度一樣乘盼,所以任務(wù)2和任務(wù)4優(yōu)先于block2執(zhí)行

  • 最后執(zhí)行block2中的任務(wù)3

  • 在極端情況下,可能出現(xiàn) 任務(wù)2先于任務(wù)1任務(wù)5執(zhí)行影所,原因是出現(xiàn)了當(dāng)前主線程卡頓或者延遲的情況

代碼修改
  • 【修改1】:將并行隊(duì)列 改成 串行隊(duì)列蹦肴,對(duì)結(jié)果沒有任何影響僚碎,順序仍然是 1 5 2 4 3

  • 【修改2】:在任務(wù)5之前猴娩,休眠2s,即sleep(2)勺阐,執(zhí)行的順序?yàn)椋? 2 4 3 5,原因是因?yàn)镮/O的打印卷中,相比于休眠2s,復(fù)雜度更簡單渊抽,所以異步block1 會(huì)先于任務(wù)5執(zhí)行蟆豫。當(dāng)然如果主隊(duì)列堵塞,會(huì)出現(xiàn)其他的執(zhí)行順序

【面試題 - 2】異步函數(shù)嵌套同步函數(shù) + 并發(fā)隊(duì)列

下面代碼的輸出順序是什么懒闷?

- (void)interview02{
    //并發(fā)隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("com.CJL.Queue", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    //異步函數(shù)
    dispatch_async(queue, ^{
        NSLog(@"2");
        //同步函數(shù)
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

----------打印結(jié)果-----------
輸出順序?yàn)椋? 5 2 3 4
分析
  • 任務(wù)1 和 任務(wù)5的分析同前面一致十减,執(zhí)行順序?yàn)?任務(wù)1 任務(wù)5 異步block

  • 在異步block中,首先執(zhí)行 任務(wù)2 愤估,然后走到 同步block 帮辟,由于 同步函數(shù)會(huì)阻塞主線程,所以任務(wù)4需要等待任務(wù)3執(zhí)行完成后玩焰,才能執(zhí)行由驹,所以異步block中的執(zhí)行順序是:任務(wù)2 任務(wù)3 任務(wù)4

面試題 - 3】異步函數(shù)嵌套同步函數(shù) + 串行隊(duì)列(即同步隊(duì)列)

下面代碼的執(zhí)行順序是什么?會(huì)出現(xiàn)什么情況昔园?為什么蔓榄?

- (void)interview03{
    // 同步隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("com.CJL.Queue", NULL);
    NSLog(@"1");
    // 異步函數(shù)
    dispatch_async(queue, ^{
        NSLog(@"2");
        // 同步函數(shù)
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
}

----------打印結(jié)果-----------
輸出順序?yàn)椋? 5 2 死鎖崩潰
分析

如下圖所示并炮,紅色表示任務(wù)執(zhí)行順序,黑色虛線表示等待

  • 首先執(zhí)行任務(wù)1甥郑,接下來是異步block逃魄,并不會(huì)阻塞主線程,相比任務(wù)5而言壹若,復(fù)雜度更高嗅钻,所以優(yōu)先執(zhí)行任務(wù)5,在執(zhí)行異步block

  • 異步block中店展,先執(zhí)行任務(wù)2养篓,接下來是同步block,同步函數(shù)會(huì)阻塞線程赂蕴,所以執(zhí)行任務(wù)4需要等待任務(wù)3執(zhí)行完成柳弄,而任務(wù)3的執(zhí)行,需要等待異步block執(zhí)行完成概说,相當(dāng)于任務(wù)3等待任務(wù)4完成

  • 所以就造成了任務(wù)4等待任務(wù)3碧注,任務(wù)3等待任務(wù)4,即互相等待的局面糖赔,就會(huì)造成死鎖萍丐,這里有個(gè)重點(diǎn)是關(guān)鍵的堆棧 slow

修改

去掉任務(wù)4,執(zhí)行順序是什么放典?

  • 還是會(huì)死鎖逝变,因?yàn)?code>任務(wù)3等待的是異步block執(zhí)行完畢,而異步block等待任務(wù)3

【面試題 - 4 - 新浪】 異步函數(shù) + 同步函數(shù) + 并發(fā)隊(duì)列

下面代碼的執(zhí)行順序是什么奋构?(答案是 AC)
A: 1230789
B: 1237890
C: 3120798
D: 2137890

- (void)interview04{
    //并發(fā)隊(duì)列
    dispatch_queue_t queue = dispatch_queue_create("com.CJL.Queue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{ // 耗時(shí)
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    
    // 同步
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    
    NSLog(@"0");

    dispatch_async(queue, ^{
        NSLog(@"7");
    });
    dispatch_async(queue, ^{
        NSLog(@"8");
    });
    dispatch_async(queue, ^{
        NSLog(@"9");
    });
}

----------打印結(jié)果-----------
輸出順序?yàn)椋海? 2 3 無序)0(7 8 9 無序)壳影,可以確定的是 0 一定在3之后,在789之前
分析
  • 任務(wù)1 和 任務(wù)2由于是異步函數(shù)+并發(fā)隊(duì)列弥臼,會(huì)開啟線程宴咧,所以沒有固定順序

  • 任務(wù)7、任務(wù)8径缅、任務(wù)9同理掺栅,會(huì)開啟線程,所以沒有固定順序

  • 任務(wù)3是同步函數(shù)+并發(fā)隊(duì)列纳猪,同步函數(shù)會(huì)阻塞主線程氧卧,但是也只會(huì)阻塞0,所以兆旬,可以確定的是 0一定在3之后假抄,在789之前

以下是不同的執(zhí)行順序的打印

【面試題 - 5 - 美團(tuán)】下面代碼中,隊(duì)列的類型有幾種

//串行隊(duì)列 - Serial Dispatch Queue
dispatch_queue_t serialQueue = dispatch_queue_create("com.CJL.Queue", NULL);
    
//并發(fā)隊(duì)列 - Concurrent Dispatch Queue
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.CJL.Queue", DISPATCH_QUEUE_CONCURRENT);
    
//主隊(duì)列 - Main Dispatch Queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
//全局并發(fā)隊(duì)列 - Global Dispatch Queue
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);

隊(duì)列總共有兩種: 并發(fā)隊(duì)列串行隊(duì)列

  • 串行隊(duì)列:serialQueue、mainQueue
  • 并發(fā)隊(duì)列:concurrentQueue宿饱、globalQueue
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熏瞄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谬以,更是在濱河造成了極大的恐慌强饮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为黎,死亡現(xiàn)場離奇詭異邮丰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铭乾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門剪廉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炕檩,你說我怎么就攤上這事斗蒋。” “怎么了笛质?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵泉沾,是天一觀的道長。 經(jīng)常有香客問我妇押,道長跷究,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任敲霍,我火速辦了婚禮俊马,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘色冀。我一直安慰自己潭袱,他們只是感情好柱嫌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布锋恬。 她就那樣靜靜地躺著,像睡著了一般编丘。 火紅的嫁衣襯著肌膚如雪与学。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天嘉抓,我揣著相機(jī)與錄音索守,去河邊找鬼。 笑死抑片,一個(gè)胖子當(dāng)著我的面吹牛卵佛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼截汪,長吁一口氣:“原來是場噩夢啊……” “哼疾牲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衙解,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤阳柔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蚓峦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舌剂,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年暑椰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了霍转。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡一汽,死狀恐怖谴忧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情角虫,我是刑警寧澤沾谓,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站戳鹅,受9級(jí)特大地震影響均驶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枫虏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一妇穴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隶债,春花似錦腾它、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赞警,卻和暖如春妓忍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愧旦。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工世剖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笤虫。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓旁瘫,卻偏偏與公主長得像祖凫,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子酬凳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354