iOS學習筆記—Runloop

轉自:http://blog.csdn.net/jjunjoe/article/details/8313016

一、Runloop簡介:

Run loops 是線程相關的的基礎框架的一部分级及。一個 run loop 就是一個事件處理 的循環(huán),用來不停的調(diào)度工作以及處理輸入事件拼卵。

使用 run loop的目的是讓你的線程在有工作的時候忙于工作,而沒工作的時候處于休眠狀態(tài)。

Runloop還可以在loop在循環(huán)中的同時響應其他輸入源虏杰,比如界面控件的按鈕讥蟆,手勢等。

Run loop 接收輸入事件來自兩種不同的來源:

輸入源(input source)和定時源 (timer source)纺阔。

輸入源傳遞異步事件,通常消息來自于其他線程或程序瘸彤。輸入源的種類:基于端口的輸入源和自定義輸入源。

定時源則傳遞同步事件,發(fā)生在特定時間或者重復的時間間隔笛钝。

Run loop 模式是所有要監(jiān)視的輸入源和定時源以及要通知的 run loop 注冊觀察 者的集合质况。

可以將 Run loop 觀察者和以下事件關聯(lián):

Run loop 入口

Run loop 何時處理一個定時器

Run loop 何時處理一個輸入源

Run loop 何時進入睡眠狀態(tài)

Run loop 何時被喚醒,但在喚醒之前要處理的事件

Run loop 終止

每次運行 Run loop,你線程的 Run loop 對會自動處理之前未處理的消息,并通知相關的觀察者。具體的順序如下:

1. 通知觀察者 Run loop 已經(jīng)啟動玻靡。

2. 通知觀察者任何即將要開始的定時器结榄。

3. 通知觀察者任何即將啟動的非基于端口的源。

4. 啟動任何準備好的非基于端口的源囤捻。

5. 如果基于端口的源準備好并處于等待狀態(tài),立即啟動;并進入步驟 9臼朗。

6. 通知觀察者線程進入休眠。

7. 將線程置于休眠直到任一下面的事件發(fā)生:

某一事件到達基于端口的源最蕾;

定時器啟動依溯;

Run loop 設置的時間已經(jīng)超時;

Run loop 被顯式喚醒瘟则。

8. 通知觀察者線程將被喚醒黎炉。

9. 處理未處理的事件

如果用戶定義的定時器啟動,處理定時器事件并重啟 Run loop。進入步驟 2醋拧。

如果輸入源啟動,傳遞相應的消息慷嗜。

如果 Run loop 被顯式喚醒而且時間還沒超時,重啟 Run loop淀弹,進入步驟 2。

10. 通知觀察者 Run loop 結束庆械。

Run loop 在你要和線程有更多的交互時才需要,比如以下情況:

使用端口或自定義輸入源來和其他線程通信薇溃;

使用線程的定時器;

Cocoa 中使用任何performSelector...的方法缭乘;

使線程周期性工作沐序。

二、舉例說明Runloop的優(yōu)點堕绩。

一般情況下策幼,當我們使用NSRunLoop的時候,代碼如下所示:

do {

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopModebeforeDate:[NSDate distantFuture]];

} while (!done);

在上面的代碼中奴紧,參數(shù)done為NO的時候特姐,當前runloop會一直接收處理其他輸入源,處理輸入源之后會再回到runloop中等待其他的輸入源黍氮;除非done為NO唐含,否則當前流程一直再runloop中。

如下面的代碼片段所示沫浆,有三個按鈕捷枯,分別對應如下三個action消息,buttonNormalThreadTestPressed专执,buttonRunloopPressed铜靶,buttonTestPressed。

buttonNormalThreadTestPressed:啟動一個線程他炊,在while循環(huán)中等待線程執(zhí)行完再接著往下運行争剿。

buttonRunloopPressed:啟動一個線程,使用runloop痊末,等待線程執(zhí)行完再接著往下運行蚕苇。

buttonTestPressed:僅僅打印兩條日志,用來測試UI是否能立即響應的凿叠。

在本測試中涩笤,待程序運行后,做如下操作對比:

1盒件、點擊buttonNormalThreadTestPressed蹬碧,然后立刻點擊buttonTestPressed,查看日志輸出炒刁。

2恩沽、待1完成后,點擊buttonRunloopPressed翔始,然后立刻點擊buttonTestPressed罗心,查看日志輸出里伯,跟1的日志做對比,即可以發(fā)現(xiàn)步驟2即使線程沒有完成渤闷,在runloop等待過程中疾瓮,界面仍然能夠響應。

BOOL threadProcess1Finished =NO;

-(void)threadProce1{

NSLog(@"Enter threadProce1.");

for (int i=0; i<5;i++) {

NSLog(@"InthreadProce1 count = %d.", i);

sleep(1);

}

threadProcess1Finished =YES;

NSLog(@"Exit threadProce1.");

}

BOOL threadProcess2Finished =NO;

-(void)threadProce2{

NSLog(@"Enter threadProce2.");

for (int i=0; i<5;i++) {

NSLog(@"InthreadProce2 count = %d.", i);

sleep(1);

}

threadProcess2Finished =YES;

NSLog(@"Exit threadProce2.");

}

- (IBAction)buttonNormalThreadTestPressed:(UIButton *)sender {

NSLog(@"EnterbuttonNormalThreadTestPressed");

threadProcess1Finished =NO;

NSLog(@"Start a new thread.");

[NSThreaddetachNewThreadSelector: @selector(threadProce1)

toTarget: self

withObject: nil];

// 通常等待線程處理完后再繼續(xù)操作的代碼如下面的形式飒箭。

// 在等待線程threadProce1結束之前狼电,調(diào)用buttonTestPressed,界面沒有響應弦蹂,直到threadProce1運行完漫萄,才打印buttonTestPressed里面的日志。

while (!threadProcess1Finished) {

[NSThreadsleepForTimeInterval: 0.5];

}

NSLog(@"ExitbuttonNormalThreadTestPressed");

}

- (IBAction)buttonRunloopPressed:(id)sender {

NSLog(@"Enter buttonRunloopPressed");

threadProcess2Finished =NO;

NSLog(@"Start a new thread.");

[NSThreaddetachNewThreadSelector: @selector(threadProce2)

toTarget: self

withObject: nil];

// 使用runloop盈匾,情況就不一樣了。

// 在等待線程threadProce2結束之前毕骡,調(diào)用buttonTestPressed削饵,界面立馬響應,并打印buttonTestPressed里面的日志未巫。

// 這就是runloop的神奇所在

while (!threadProcess2Finished) {

NSLog(@"Begin runloop");

[[NSRunLoopcurrentRunLoop] runMode:NSDefaultRunLoopMode

beforeDate: [NSDate distantFuture]];

NSLog(@"End runloop.");

}

NSLog(@"Exit buttonRunloopPressed");

}

- (IBAction)buttonTestPressed:(id)sender{

NSLog(@"Enter buttonTestPressed");

NSLog(@"Exit buttonTestPressed");

}

日志信息如下:

2013-04-07 14:25:22.829 Runloop[657:11303] EnterbuttonNormalThreadTestPressed

2013-04-07 14:25:22.830 Runloop[657:11303] Start a new thread.

2013-04-07 14:25:22.831 Runloop[657:1250f] Enter threadProce1.

2013-04-07 14:25:22.832 Runloop[657:1250f] In threadProce1 count = 0.

2013-04-07 14:25:23.833 Runloop[657:1250f] In threadProce1 count = 1.

2013-04-07 14:25:24.834 Runloop[657:1250f] In threadProce1 count = 2.

2013-04-07 14:25:25.835 Runloop[657:1250f] In threadProce1 count = 3.

2013-04-07 14:25:26.837 Runloop[657:1250f] In threadProce1 count = 4.

2013-04-07 14:25:27.839 Runloop[657:1250f] Exit threadProce1.

2013-04-07 14:25:27.840 Runloop[657:11303]Exit buttonNormalThreadTestPressed

2013-04-07 14:25:27.841 Runloop[657:11303]Enter buttonTestPressed

2013-04-07 14:25:27.842 Runloop[657:11303] Exit buttonTestPressed

2013-04-07 14:25:27.843 Runloop[657:11303] Enter buttonTestPressed

2013-04-07 14:25:27.844 Runloop[657:11303] Exit buttonTestPressed

2013-04-07 14:43:41.790 Runloop[657:11303] Enter buttonRunloopPressed

2013-04-07 14:43:41.790 Runloop[657:11303] Start a new thread.

2013-04-07 14:43:41.791 Runloop[657:11303] Begin runloop

2013-04-07 14:43:41.791 Runloop[657:14f0b] Enter threadProce2.

2013-04-07 14:43:41.792 Runloop[657:14f0b] In threadProce2 count = 0.

2013-04-07 14:43:42.542 Runloop[657:11303] End runloop.

2013-04-07 14:43:42.543 Runloop[657:11303] Begin runloop

2013-04-07 14:43:42.694 Runloop[657:11303]Enter buttonTestPressed

2013-04-07 14:43:42.694 Runloop[657:11303]Exit buttonTestPressed

2013-04-07 14:43:42.695 Runloop[657:11303] End runloop.

2013-04-07 14:43:42.696 Runloop[657:11303] Begin runloop

2013-04-07 14:43:42.793 Runloop[657:14f0b] In threadProce2 count = 1.

2013-04-07 14:43:43.326 Runloop[657:11303] End runloop.

2013-04-07 14:43:43.327 Runloop[657:11303] Begin runloop

2013-04-07 14:43:43.438 Runloop[657:11303]Enter buttonTestPressed

2013-04-07 14:43:43.438 Runloop[657:11303]Exit buttonTestPressed

2013-04-07 14:43:43.439 Runloop[657:11303] End runloop.

2013-04-07 14:43:43.440 Runloop[657:11303] Begin runloop

2013-04-07 14:43:43.795 Runloop[657:14f0b] In threadProce2 count = 2.

2013-04-07 14:43:44.797 Runloop[657:14f0b] In threadProce2 count = 3.

2013-04-07 14:43:45.798 Runloop[657:14f0b] In threadProce2 count = 4.

2013-04-07 14:43:46.800 Runloop[657:14f0b] Exit threadProce2.

三窿撬、Runloop簡單實例:

- (void)viewDidLoad

{

[superviewDidLoad];

// Doany additional setup after loading the view, typically from a nib.

[NSThreaddetachNewThreadSelector: @selector(newThreadProcess)

toTarget: self

withObject: nil];

}

- (void)newThreadProcess

{

@autoreleasepool {

////獲得當前thread的Runloop

NSRunLoop* myRunLoop = [NSRunLoop currentRunLoop];

//設置Run loop observer的運行環(huán)境

CFRunLoopObserverContext context = {0,self,NULL,NULL,NULL};

//創(chuàng)建Run loop observer對象

//第一個參數(shù)用于分配observer對象的內(nèi)存

//第二個參數(shù)用以設置observer所要關注的事件,詳見回調(diào)函數(shù)myRunLoopObserver中注釋

//第三個參數(shù)用于標識該observer是在第一次進入runloop時執(zhí)行還是每次進入run loop處理時均執(zhí)行

//第四個參數(shù)用于設置該observer的優(yōu)先級

//第五個參數(shù)用于設置該observer的回調(diào)函數(shù)

//第六個參數(shù)用于設置該observer的運行環(huán)境

CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault,kCFRunLoopAllActivities, YES, 0, &myRunLoopObserver, &context);

if(observer)

{

//將Cocoa的NSRunLoop類型轉換成CoreFoundation的CFRunLoopRef類型

CFRunLoopRef cfRunLoop = [myRunLoop getCFRunLoop];

//將新建的observer加入到當前thread的runloop

CFRunLoopAddObserver(cfRunLoop, observer, kCFRunLoopDefaultMode);

}

//

[NSTimerscheduledTimerWithTimeInterval: 1

target: self

selector:@selector(timerProcess)

userInfo: nil

repeats: YES];

NSInteger loopCount = 2;

do{

//啟動當前thread的loop直到所指定的時間到達叙凡,在loop運行時劈伴,runloop會處理所有來自與該run loop聯(lián)系的inputsource的數(shù)據(jù)

//對于本例與當前run loop聯(lián)系的inputsource只有一個Timer類型的source。

//該Timer每隔1秒發(fā)送觸發(fā)事件給runloop握爷,run loop檢測到該事件時會調(diào)用相應的處理方法跛璧。

//由于在run loop添加了observer且設置observer對所有的runloop行為都感興趣。

//當調(diào)用runUnitDate方法時新啼,observer檢測到runloop啟動并進入循環(huán)追城,observer會調(diào)用其回調(diào)函數(shù),第二個參數(shù)所傳遞的行為是kCFRunLoopEntry燥撞。

//observer檢測到runloop的其它行為并調(diào)用回調(diào)函數(shù)的操作與上面的描述相類似座柱。

[myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];

//當run loop的運行時間到達時,會退出當前的runloop物舒。observer同樣會檢測到runloop的退出行為并調(diào)用其回調(diào)函數(shù)色洞,第二個參數(shù)所傳遞的行為是kCFRunLoopExit。

loopCount--;

}while (loopCount);

}

}

void myRunLoopObserver(CFRunLoopObserverRef observer,CFRunLoopActivity activity,void *info)

{

switch (activity) {

//The entrance of the run loop, beforeentering the event processing loop.

//This activity occurs once for each callto CFRunLoopRun and CFRunLoopRunInMode

case kCFRunLoopEntry:

NSLog(@"run loop entry");

break;

//Inside the event processing loop beforeany timers are processed

case kCFRunLoopBeforeTimers:

NSLog(@"run loop before timers");

break;

//Inside the event processing loop beforeany sources are processed

case kCFRunLoopBeforeSources:

NSLog(@"run loop before sources");

break;

//Inside the event processing loop beforethe run loop sleeps, waiting for a source or timer to fire.

//This activity does not occur ifCFRunLoopRunInMode is called with a timeout of 0 seconds.

//It also does not occur in a particulariteration of the event processing loop if a version 0 source fires

case kCFRunLoopBeforeWaiting:

NSLog(@"run loop before waiting");

break;

//Inside the event processing loop afterthe run loop wakes up, but before processing the event that woke it up.

//This activity occurs only if the run loopdid in fact go to sleep during the current loop

case kCFRunLoopAfterWaiting:

NSLog(@"run loop after waiting");

break;

//The exit of the run loop, after exitingthe event processing loop.

//This activity occurs once for each callto CFRunLoopRun and CFRunLoopRunInMode

case kCFRunLoopExit:

NSLog(@"run loop exit");

break;

/*

A combination of all the precedingstages

case kCFRunLoopAllActivities:

break;

*/

default:

break;

}

}

- (void)timerProcess{

for (int i=0; i<5; i++) {

NSLog(@"In timerProcess count = %d.", i);

sleep(1);

}

}

調(diào)試打印信息如下:

2012-12-18 09:51:14.174 Texta[645:14807] run loop entry

2012-12-18 09:51:14.175 Texta[645:14807] run loop before timers

2012-12-18 09:51:14.176 Texta[645:14807] run loop before sources

2012-12-18 09:51:14.177 Texta[645:14807] run loop before waiting

2012-12-18 09:51:15.174 Texta[645:14807] run loop after waiting

2012-12-18 09:51:15.176 Texta[645:14807] In timerProcess count = 0.

2012-12-18 09:51:16.178 Texta[645:14807] In timerProcess count = 1.

2012-12-18 09:51:17.181 Texta[645:14807] In timerProcess count = 2.

2012-12-18 09:51:18.183 Texta[645:14807] In timerProcess count = 3.

2012-12-18 09:51:19.185 Texta[645:14807] In timerProcess count = 4.

2012-12-18 09:51:20.187 Texta[645:14807] run loop exit

2012-12-18 09:51:20.189 Texta[645:14807] run loop entry

2012-12-18 09:51:20.190 Texta[645:14807] run loop before timers

2012-12-18 09:51:20.191 Texta[645:14807] run loop before sources

2012-12-18 09:51:20.191 Texta[645:14807] run loop before waiting

2012-12-18 09:51:21.174 Texta[645:14807] run loop after waiting

2012-12-18 09:51:21.176 Texta[645:14807] In timerProcess count = 0.

2012-12-18 09:51:22.178 Texta[645:14807] In timerProcess count = 1.

2012-12-18 09:51:23.181 Texta[645:14807] In timerProcess count = 2.

2012-12-18 09:51:24.183 Texta[645:14807] In timerProcess count = 3.

2012-12-18 09:51:25.185 Texta[645:14807] In timerProcess count = 4.

2012-12-18 09:51:26.187 Texta[645:14807] run loop exit

四冠胯、Runloop可以阻塞線程火诸,等待其他線程執(zhí)行后再執(zhí)行。

比如:

BOOL StopFlag =NO;

- (void)viewDidLoad

{

[superviewDidLoad];

// Doany additional setup after loading the view, typically from a nib.

StopFlag =NO;

NSLog(@"Start a new thread.");

[NSThreaddetachNewThreadSelector: @selector(newThreadProc)

toTarget:self

withObject: nil];

while (!StopFlag) {

NSLog(@"Beginrunloop");

[[NSRunLoopcurrentRunLoop] runMode:NSDefaultRunLoopMode

beforeDate: [NSDate distantFuture]];

NSLog(@"Endrunloop.");

}

NSLog(@"OK");

}

-(void)newThreadProc{

NSLog(@"Enter newThreadProc.");

for (int i=0; i<10; i++) {

NSLog(@"InnewThreadProc count = %d.", i);

sleep(1);

}

StopFlag =YES;

NSLog(@"Exit newThreadProc.");

}

}

調(diào)試打印信息如下:

2012-12-18 08:50:34.220 Runloop[374:11303] Start a new thread.

2012-12-18 08:50:34.222 Runloop[374:11303] Begin runloop

2012-12-18 08:50:34.222 Runloop[374:14b03] Enter newThreadProc.

2012-12-18 08:50:34.223 Runloop[374:14b03] In newThreadProc count = 0.

2012-12-18 08:50:35.225 Runloop[374:14b03] In newThreadProc count = 1.

2012-12-18 08:50:36.228 Runloop[374:14b03] In newThreadProc count = 2.

2012-12-18 08:50:37.230 Runloop[374:14b03] In newThreadProc count = 3.

2012-12-18 08:50:38.233 Runloop[374:14b03] In newThreadProc count = 4.

2012-12-18 08:50:39.235 Runloop[374:14b03] In newThreadProc count = 5.

2012-12-18 08:50:40.237 Runloop[374:14b03] In newThreadProc count = 6.

2012-12-18 08:50:41.240 Runloop[374:14b03] In newThreadProc count = 7.

2012-12-18 08:50:42.242 Runloop[374:14b03] In newThreadProc count = 8.

2012-12-18 08:50:43.245 Runloop[374:14b03] In newThreadProc count = 9.

2012-12-18 08:50:44.247 Runloop[374:14b03] Exit newThreadProc.

2012-12-18 08:51:00.000 Runloop[374:11303] End runloop.

2012-12-18 08:51:00.001 Runloop[374:11303] OK

從調(diào)試打印信息可以看到荠察,while循環(huán)后執(zhí)行的語句會在很長時間后才被執(zhí)行惭蹂。因為伞插,改變變量StopFlag的值,runloop對象根本不知道盾碗,runloop在這個時候未被喚醒媚污。有其他事件在某個時點喚醒了主線程,這才結束了while循環(huán)廷雅,但延緩的時長總是不定的耗美。。

將代碼稍微修改一下:

[[NSRunLoopcurrentRunLoop] runMode:NSDefaultRunLoopMode

beforeDate: [NSDatedateWithTimeIntervalSinceNow: 1]];

縮短runloop的休眠時間航缀,看起來解決了上面出現(xiàn)的問題商架。

但這樣會導致runloop被經(jīng)常性的喚醒,違背了runloop的設計初衷芥玉。runloop的目的就死讓你的線程在有工作的時候忙于工作蛇摸,而沒工作的時候處于休眠狀態(tài)。

最后灿巧,看下下面正確的寫法:

BOOL StopFlag =NO;

- (void)viewDidLoad

{

[superviewDidLoad];

// Doany additional setup after loading the view, typically from a nib.

StopFlag =NO;

NSLog(@"Start a new thread.");

[NSThreaddetachNewThreadSelector: @selector(newThreadProc)

toTarget: self

withObject: nil];

while (!StopFlag) {

NSLog(@"Beginrunloop");

[[NSRunLoopcurrentRunLoop] runMode:NSDefaultRunLoopMode

beforeDate: [NSDatedistantFuture]];

NSLog(@"Endrunloop.");

}

NSLog(@"OK");

}

-(void)newThreadProc{

NSLog(@"Enter newThreadProc.");

for (int i=0; i<10; i++) {

NSLog(@"InnewThreadProc count = %d.", i);

sleep(1);

}

[selfperformSelectorOnMainThread: @selector(setEnd)

withObject: nil

waitUntilDone: NO];

NSLog(@"Exit newThreadProc.");

}

-(void)setEnd{

StopFlag = YES;

}

調(diào)試打印信息如下:

2012-12-18 09:05:17.161 Runloop[410:11303] Start a new thread.

2012-12-18 09:05:17.163 Runloop[410:14a03] Enter newThreadProc.

2012-12-18 09:05:17.164 Runloop[410:14a03] In newThreadProc count = 0.

2012-12-18 09:05:17.165 Runloop[410:11303] Begin runloop

2012-12-18 09:05:18.166 Runloop[410:14a03] In newThreadProc count = 1.

2012-12-18 09:05:19.168 Runloop[410:14a03] In newThreadProc count = 2.

2012-12-18 09:05:20.171 Runloop[410:14a03] In newThreadProc count = 3.

2012-12-18 09:05:21.173 Runloop[410:14a03] In newThreadProc count = 4.

2012-12-18 09:05:22.175 Runloop[410:14a03] In newThreadProc count = 5.

2012-12-18 09:05:23.178 Runloop[410:14a03] In newThreadProc count = 6.

2012-12-18 09:05:24.180 Runloop[410:14a03] In newThreadProc count = 7.

2012-12-18 09:05:25.182 Runloop[410:14a03] In newThreadProc count = 8.

2012-12-18 09:05:26.185 Runloop[410:14a03] In newThreadProc count = 9.

2012-12-18 09:05:27.188 Runloop[410:14a03] Exit newThreadProc.

2012-12-18 09:05:27.188 Runloop[410:11303] End runloop.

2012-12-18 09:05:27.189 Runloop[410:11303] OK

把直接設置變量赶袄,改為向主線程發(fā)送消息,喚醒runloop抠藕,延時問題解決饿肺。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盾似,隨后出現(xiàn)的幾起案子敬辣,更是在濱河造成了極大的恐慌,老刑警劉巖零院,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溉跃,死亡現(xiàn)場離奇詭異,居然都是意外死亡告抄,警方通過查閱死者的電腦和手機喊积,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玄妈,“玉大人乾吻,你說我怎么就攤上這事∧怛撸” “怎么了绎签?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酝锅。 經(jīng)常有香客問我诡必,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任爸舒,我火速辦了婚禮壮韭,結果婚禮上肢娘,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好密任,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布滔吠。 她就那樣靜靜地躺著烂完,像睡著了一般赂蕴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唱捣,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天两蟀,我揣著相機與錄音,去河邊找鬼震缭。 笑死赂毯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的拣宰。 我是一名探鬼主播党涕,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼徐裸!你這毒婦竟也來了?” 一聲冷哼從身側響起啸盏,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤重贺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后回懦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體气笙,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年怯晕,在試婚紗的時候發(fā)現(xiàn)自己被綠了潜圃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡舟茶,死狀恐怖谭期,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吧凉,我是刑警寧澤隧出,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站阀捅,受9級特大地震影響胀瞪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饲鄙,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一凄诞、第九天 我趴在偏房一處隱蔽的房頂上張望圆雁。 院中可真熱鬧,春花似錦帆谍、人聲如沸伪朽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驱负。三九已至,卻和暖如春患雇,著一層夾襖步出監(jiān)牢的瞬間跃脊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工苛吱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留酪术,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓翠储,卻偏偏與公主長得像绘雁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子援所,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

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