玩轉(zhuǎn) GCD

玩轉(zhuǎn) GCD

GCD介紹


Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的解決方法
基于C語言牌借,提供了非常多強(qiáng)大的函數(shù)
GCD和其他多線程技術(shù)方案,如NSThread,NSOperationQueue,NSInvocationOperation等相比,使用起來更加方便翰灾。

術(shù)語


同步 (Synchronous)

在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
提交的任務(wù)在執(zhí)行完成后才會返回
同步函數(shù): dispatch_sync()

異步 (Asynchronous)

在新線程中執(zhí)行任務(wù)稚茅,具備開啟新線程的能力
提交的任務(wù)立刻返回纸淮,在后臺隊列中執(zhí)行
異步函數(shù): dispatch_async()

串行 (Serial)

一個任務(wù)執(zhí)行完畢后,再執(zhí)行下一個任務(wù)

并發(fā) (Concurrent)

多個任務(wù)同時執(zhí)行(自動開啟多個線程),只有在異步函數(shù)下才有效

描述 說明
queue 隊列
main 主隊列
global 全局隊列
dispatch_queue_t 描述隊列
dispatch_block_t 描述任務(wù)
dispatch_once_t 描述一次性
dispatch_time_t 描述時間
dispatch_group_t 描述隊列組
dispatch_semaphore_t 描述信號量
函數(shù) 說明
dispatch_sync() 同步執(zhí)行
dispatch_async() 異步執(zhí)行
dispatch_after() 延時執(zhí)行
dispatch_once() 一次性執(zhí)行
dispatch_apply() 提交隊列
dispatch_queue_create() 創(chuàng)建隊列
dispatch_group_create() 創(chuàng)建隊列組
dispatch_group_async() 提交任務(wù)到隊列組
dispatch_group_enter() / dispatch_group_leave() 將隊列組中的任務(wù)未執(zhí)行完畢的任務(wù)數(shù)目加減1(兩個函數(shù)要配合使用)
dispatch_group_notify() 監(jiān)聽隊列組執(zhí)行完畢
dispatch_group_wait() 設(shè)置等待時間(返回 0成功,1失敗)
注意:

1.所有的執(zhí)行都放到隊列中(queue)峰锁,隊列的特點(diǎn)是FIFO(先提交的先執(zhí)行)
2.必須在主線程訪問 UIKit 的類
3.并發(fā)隊列只在異步函數(shù)下才有效

基本使用


 NSLog(@"當(dāng)前線程: %@", [NSThread currentThread]);
 //獲取主隊列
 dispatch_queue_t mainQueue = dispatch_get_main_queue();
 
 //獲取全局并發(fā)隊列
 dispatch_queue_t otherQueue =   dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
 //同步函數(shù)(在當(dāng)前線程中執(zhí)行,不具備開啟新線程的能力)
 dispatch_sync(otherQueue, ^{
      NSLog(@"同步 %@", [NSThread currentThread]);
 });
    
 //異步函數(shù)(在另一條線程中執(zhí)行,具備開啟新線程的能力)
 dispatch_async(otherQueue, ^{
      NSLog(@"異步 %@", [NSThread currentThread]);
 });
    
 //輸出:   當(dāng)前線程: <NSThread: 0x7f81bac06670>{number = 1, name = main}
 //輸出:   同步 <NSThread: 0x7f81bac06670>{number = 1, name = main}
 //輸出:   異步 <NSThread: 0x7f81bae35be0>{number = 3, name = (null)}
延時執(zhí)行 dispatch_after()

dispatch_after()延遲一段時間把一項任務(wù)提交到隊列中執(zhí)行萎馅,返回之后就不能取消
常用來在在主隊列上延遲執(zhí)行一項任務(wù)

    NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);

    //GCD延時調(diào)用(主線程)(主隊列)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"GCD延時(主線程) %@", [NSThread currentThread]);
    });
    
    //GCD延時調(diào)用(其他線程)(全局并發(fā)隊列)
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"GCD延時(其他線程) %@", [NSThread currentThread]);
    });

    //輸出:   當(dāng)前線程 <NSThread: 0x7f8cb9701990>{number = 1, name = main}
    //輸出:   GCD延時(主線程) <NSThread: 0x7f8cb9701990>{number = 1, name = main}
    //輸出:   GCD延時(其他線程) <NSThread: 0x7f8cb9513ee0>{number = 3, name = (null)}
一次性執(zhí)行 dispatch_once()

整個程序運(yùn)行中,只會執(zhí)行一次 (默認(rèn)線程是安全的)
dispatch_once() 以線程安全的方式執(zhí)行且僅執(zhí)行其代碼塊一次

    for (NSInteger i = 0; i < 10; i++) {
      
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"GCD一次性執(zhí)行(默認(rèn)線程是安全的)");
        });
        
    }

 //輸出:   GCD一次性執(zhí)行(默認(rèn)線程是安全的)
//使用GCD初始化單例
+ (instancetype)sharedManager { 
  
    static PhotoManager *sharedPhotoManager = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
        sharedPhotoManager = [[PhotoManager alloc] init]; 
    }); 

    return sharedPhotoManager; 
} 
提交 dispatch_apply()

把一項任務(wù)提交到隊列中多次執(zhí)行,具體是并行執(zhí)行還是串行執(zhí)行由隊列本身決定
dispatch_apply不會立刻返回虹蒋,在執(zhí)行完畢后才會返回糜芳,是同步的調(diào)用。

隊列

任務(wù)1,任務(wù)2依次執(zhí)行,所有任務(wù)都執(zhí)行成功后回到主線程
(效率不高)

 NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
   
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //全局并發(fā)隊列
        for (NSInteger i = 0; i < 5; i++) {
            NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
        }
        
        for (NSInteger i = 0; i < 5; i++) {
            NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //主隊列
            NSLog(@"主線程執(zhí)行(刷新UI) %@", [NSThread currentThread]);
        });
        
    });
    
    //輸出:   當(dāng)前線程 <NSThread: 0x7fa78040b8b0>{number = 1, name = main}
    //輸出:   任務(wù)1 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7f9da1416a00>{number = 3, name = (null)}
    //輸出:   主線程(刷新UI) <NSThread: 0x7f9da1705940>{number = 1, name = main}
隊列組

任務(wù)1,任務(wù)2同時執(zhí)行,所有任務(wù)都執(zhí)行成功后回到主線程
(效率高)

    NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
    
    //(1)創(chuàng)建一個隊列組
    dispatch_group_t group= dispatch_group_create();
    
    //(2)開啟任務(wù)1
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       
        for (NSInteger i = 0; i < 5; i++) {
            NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
        }
        
    });
    
    //(3)開啟任務(wù)2
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       
        for (NSInteger i = 0; i < 5; i++) {
            NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
        }
        
    });
    
    //(4)所有任務(wù)執(zhí)行完畢,回到主線程
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
        NSLog(@"主線程(刷新UI) %@", [NSThread currentThread]);
        
    });
    
    //輸出:   當(dāng)前線程 <NSThread: 0x7fd951704e70>{number = 1, name = main}
    //輸出:   任務(wù)1 <NSThread: 0x7ff65a50b4d0>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7ff65a50b4d0>{number = 3, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7ff65a50b4d0>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7ff65a697770>{number = 4, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7ff65a697770>{number = 4, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7ff65a50b4d0>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7ff65a697770>{number = 4, name = (null)}
    //輸出:   任務(wù)1 <NSThread: 0x7ff65a50b4d0>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7ff65a697770>{number = 4, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7ff65a697770>{number = 4, name = (null)}
    //輸出:   主線程(刷新UI) <NSThread: 0x7ff65a406fb0>{number = 1, name = main}

串行與并發(fā)


各個隊列的執(zhí)行效果
串行隊列
串行隊列

一個任務(wù)執(zhí)行完畢后魄衅,再執(zhí)行下一個任務(wù)
主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列中的任務(wù),都會放到主線程中執(zhí)行

    //(1)使用dispatch_queue_create函數(shù)創(chuàng)建串行隊列
    //參數(shù)1: 隊列名稱
 //參數(shù)2: 隊列屬性 (一般用NULL)
    dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", NULL);
    
    //(2)使用主隊列(跟主線程相關(guān)聯(lián)的隊列)
    dispatch_queue_t serialMainQueue = dispatch_get_main_queue();
并發(fā)隊列
并發(fā)隊列

多個任務(wù)并發(fā)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù))

<u>并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效!!!</u>

GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊列峭竣,供整個應(yīng)用使用,不需要手動創(chuàng)建

并發(fā)隊列優(yōu)先級 快捷值 優(yōu)先級
DISPATCH_QUEUE_PRIORITY_HIGH 2
DISPATCH_QUEUE_PRIORITY_DEFAULT 0 中(默認(rèn))
DISPATCH_QUEUE_PRIORITY_LOW (-2)
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后臺
 //(1)使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊列
    //參數(shù)1: 優(yōu)先級
 //參數(shù)2: 暫時無用參數(shù) (傳0)
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
異步函數(shù)_并發(fā)隊列

(開啟新線程,并發(fā)執(zhí)行任務(wù))

    NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
    });
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
    });
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"任務(wù)3 %@", [NSThread currentThread]);
    });
    
    //輸出:   當(dāng)前線程 <NSThread: 0x7fbe83c067c0>{number = 1, name = main}
    //輸出:   任務(wù)1 <NSThread: 0x7fb84160ed90>{number = 3, name = (null)}
    //輸出:   任務(wù)3 <NSThread: 0x7fb841752940>{number = 4, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7fb8414167b0>{number = 5, name = (null)}
異步函數(shù)_串行隊列

(開啟新線程,串行執(zhí)行任務(wù))

    NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
    //創(chuàng)建串行隊列
    dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", NULL);
    
    dispatch_async(serialQueue, ^{
        NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
    });
    
    dispatch_async(serialQueue, ^{
        NSLog(@"任務(wù)3 %@", [NSThread currentThread]);
    });
    
    //輸出:   當(dāng)前線程 <NSThread: 0x7fc192e05380>{number = 1, name = main}
    //輸出:   任務(wù)1 <NSThread: 0x7fc192c16670>{number = 3, name = (null)}
    //輸出:   任務(wù)2 <NSThread: 0x7fc192c16670>{number = 3, name = (null)}
    //輸出:   任務(wù)3 <NSThread: 0x7fc192c16670>{number = 3, name = (null)}
同步函數(shù)_并發(fā)隊列

(不會開啟新線程,并發(fā)執(zhí)行任務(wù)失效!)

    NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
    });
    
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
    });
    
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務(wù)3 %@", [NSThread currentThread]);
    });
    
    //輸出:   當(dāng)前線程 <NSThread: 0x7fa0dbf02e20>{number = 1, name = main}
    //輸出:   任務(wù)1 <NSThread: 0x7fa0dbf02e20>{number = 1, name = main}
    //輸出:   任務(wù)2 <NSThread: 0x7fa0dbf02e20>{number = 1, name = main}
    //輸出:   任務(wù)3 <NSThread: 0x7fa0dbf02e20>{number = 1, name = main}
同步函數(shù)_串行隊列

(不會開啟新線程,串行執(zhí)行任務(wù))

 NSLog(@"當(dāng)前線程 %@", [NSThread currentThread]);
 //創(chuàng)建串行隊列
 dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", NULL);
 dispatch_sync(serialQueue, ^{
     NSLog(@"任務(wù)1 %@", [NSThread currentThread]);
 });

 dispatch_sync(serialQueue, ^{
      NSLog(@"任務(wù)2 %@", [NSThread currentThread]);
 });

 dispatch_sync(serialQueue, ^{
     NSLog(@"任務(wù)3 %@", [NSThread currentThread]);
 });

 //輸出:   當(dāng)前線程 <NSThread: 0x7f8c0b407f00>{number = 1, name = main}
 //輸出:   任務(wù)1 <NSThread: 0x7f8c0b407f00>{number = 1, name = main}
 //輸出:   任務(wù)2 <NSThread: 0x7f8c0b407f00>{number = 1, name = main}
 //輸出:   任務(wù)3 <NSThread: 0x7f8c0b407f00>{number = 1, name = main}

多個網(wǎng)絡(luò)請求示例

- (void)exampleMoreNetwork{
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t serialQueue = dispatch_queue_create("magic_gcd_group", DISPATCH_QUEUE_SERIAL);
    
    // 網(wǎng)絡(luò)請求1
    dispatch_group_enter(group);
    dispatch_group_async(group, serialQueue, ^{
        [[MagicNetworkManager shareManager] GET:@"網(wǎng)絡(luò)請求1" Parameters:nil Success:^(NSURLResponse *response, id responseObject) {
            dispatch_group_leave(group);
        } Failure:^(NSURLResponse *response, id error) {
            dispatch_group_leave(group);
        }];
    });
    
    // 網(wǎng)絡(luò)請求2
    dispatch_group_enter(group);
    dispatch_group_async(group, serialQueue, ^{
        [[MagicNetworkManager shareManager] GET:@"網(wǎng)絡(luò)請求2" Parameters:nil Success:^(NSURLResponse *response, id responseObject) {
            dispatch_group_leave(group);
        } Failure:^(NSURLResponse *response, id error) {
            dispatch_group_leave(group);
        }];
    });
    
    // 所有網(wǎng)絡(luò)請求結(jié)束
    dispatch_group_notify(group, serialQueue, ^{
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                // 主線程刷新UI
            });
        });
    });
    
}

多張圖片上傳示例

- (void)networkUploadWithURLString:(NSString *)URLString images:(NSMutableArray *)images {
    
    NSMutableArray *result = [NSMutableArray array];
    for (NSInteger i = 0; i < images.count; i++) {
        [result addObject:[NSNull null]];
    }
    
    dispatch_group_t group = dispatch_group_create();
    
    for (NSInteger i = 0; i < images.count; i++) {
        
        dispatch_group_enter(group);
        
        //1. 圖片存放地址
        NSString *url = URLString;
        //2. 圖片名稱自定義
        NSString *imageName = [[NSDate date] formattedDateWithFormat:@"yyyyMMddHHmmss"];
        NSString *fileName = [NSString stringWithFormat:@"%@_%ld.png",imageName,i];
        //3. 圖片二進(jìn)制文件
        NSData *imageData = UIImagePNGRepresentation(images[i]);
        //NSLog(@"文件大小: %ld k", (long)(imageData.length / 1024));
        //4. 發(fā)起網(wǎng)絡(luò)請求
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"application/json", @"text/html", nil];
        [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            [formData appendPartWithFileData:imageData name:@"file" fileName:fileName mimeType:@"image/png"];
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            NSLog(@"第 %d 張圖片上傳成功: %@", (int)i + 1, responseObject);
            // NSMutableArray 是線程不安全的晃虫,所以加個同步鎖
            @synchronized (result) {
                result[i] = responseObject;
            }
            dispatch_group_leave(group);
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            NSLog(@"第 %d 張圖片上傳失敗: %@", (int)i + 1, error);
            dispatch_group_leave(group);
            
        }];
        
    }
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"上傳完成!");
        for (id response in result) {
            NSLog(@"%@", response);
        }
    });
}

推薦閱讀

GCD 深入理解(一)
GCD 深入理解(二)
關(guān)于iOS多線程淺析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皆撩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哲银,更是在濱河造成了極大的恐慌扛吞,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荆责,死亡現(xiàn)場離奇詭異滥比,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)做院,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門盲泛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人键耕,你說我怎么就攤上這事寺滚。” “怎么了屈雄?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵村视,是天一觀的道長。 經(jīng)常有香客問我酒奶,道長蓖议,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任讥蟆,我火速辦了婚禮勒虾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘸彤。我一直安慰自己修然,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布质况。 她就那樣靜靜地躺著愕宋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪结榄。 梳的紋絲不亂的頭發(fā)上中贝,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機(jī)與錄音臼朗,去河邊找鬼邻寿。 笑死蝎土,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绣否。 我是一名探鬼主播誊涯,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蒜撮!你這毒婦竟也來了暴构?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤段磨,失蹤者是張志新(化名)和其女友劉穎取逾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苹支,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砾隅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沐序。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琉用。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖策幼,靈堂內(nèi)的尸體忽然破棺而出邑时,到底是詐尸還是另有隱情,我是刑警寧澤特姐,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布晶丘,位于F島的核電站,受9級特大地震影響唐含,放射性物質(zhì)發(fā)生泄漏浅浮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一捷枯、第九天 我趴在偏房一處隱蔽的房頂上張望滚秩。 院中可真熱鬧,春花似錦淮捆、人聲如沸郁油。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桐腌。三九已至,卻和暖如春苟径,著一層夾襖步出監(jiān)牢的瞬間案站,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工棘街, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蟆盐,地道東北人承边。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像舱禽,于是被迫代替她去往敵國和親炒刁。 傳聞我的和親對象是個殘疾皇子恩沽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

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