GCD學習總結

GCD概述:

OC:

/*
 GCD:Grand Central Dispatch 牛X的中樞調度器,C語言編寫
 GCD:自動管理線程的生命周期,(創建, 調度任務, 銷毀線程)
 
 任務:block (1.定制任務)
 隊列:queue (2.任務添加到隊列)
 
GCD自動從隊列queue中取出任務block執行,遵循FIFO原則,先進先出
 
任務block執行方式:
    同步的(synchronous ['s??kr?n?s]):不能開新線程
        dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
    異步的(asynchronous [e's??kr?n?s]):能開新線程
        dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
 
 隊列queue:
    并發隊列(Concurrent Dispatch Queue):
        [DISPATCH_QUEUE_CONCURRENT];
        讓多個任務并發執行,自動開啟多個線程同時執行任務;
        該功能只在異步函數(dispatch_async)下有效;
    串行隊列(Serial Dispatch Queue):
        [DISPATCH_QUEUE_SERIAL];
        讓任務順序執行;
 
 隊列queue的創建:
    并發隊列:
        方式1.dispatch_queue_create(const char *label, dispatch_queue_attr_a attr)
            label:表示該隊列的名字(標識), C語言中的字符串,創建的時候直接"abcde";
            attr:表示隊列屬性,設置并發or串行,此處使用并發(DISPATCH_QUEUE_CONCURRENT)
        方式2:獲取全局并發隊列
            dispatch_get_global_queue(dispatch_queue_priority_t priority, unsigned long flags);
            priority:隊列的優先級(高,默認,低,后臺)
            flags:此參數暫時無用,用0即可
    串行隊列:
        方式1.dispatch_queue_create(const char *label, dispatch_queue_attr_a attr)
            label:表示該隊列的名字(標識);
            attr:表示隊列屬性,設置并發or串行,此處使用串行(DISPATCH_QUEUE_SERIAL or NULL)
        方式2:使用主隊列,與主線程相關聯的隊列
            主隊列是GCD自帶的一種特殊的串行隊列;該隊列中的任務,都會在主線程中執行;
            dispatch_get_main_queue();
*/
相關練習:
#pragma mark - 并發隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)concurrentSync {
    // A.創建并發隊列concurrentQueue:
    char *queueName = "ConcurrentQueue";
    dispatch_queue_t concurrentQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);
    
    // B.創建任務block
    // 方式一: 定義一個block類型,命名為TestBlock1,然后只用該類型聲明變量block1
    // 1.定義一個block的類型,返回值void,參數為空,命名為Block1,(類似于 int),
    typedef void (^TestBlock1)();
    // 2.使用Block1類型定義一個變量block, 同時做賦值操作,賦值的內容為后面的代碼段(^{...})
    TestBlock1 block1 = ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    // 方式二: 直接定義一個名為block的block2變量
    void (^block2)() = ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // C.給并發隊列concurrentQueue,添加同步任務dispatch_sync
    // 方式1: block1變量
    dispatch_sync(concurrentQueue, block1);
    // 方式2: block2變量
    dispatch_sync(concurrentQueue, block2);
    // 方式3: 直接添加block
    dispatch_sync(concurrentQueue, ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
}

#pragma mark - 并發隊列,異步任務: 開啟新線程,任務并發執行
- (void)concurrentAsync {
    // 1.創建并發隊列 DISPATCH_QUEUE_CONCURRENT
    char *queueName = "ConcurrentQueue";
    dispatch_queue_t concurrentQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);
    
    // 2.創建任務block
    typedef void (^TestBlock)();
    TestBlock block = ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    // 3.并發隊列concurrent,添加異步任務async;
    dispatch_async(concurrentQueue, block);
    dispatch_async(concurrentQueue, block2);
    dispatch_async(concurrentQueue, ^{
        // 這是里block中的操作
        for (int i = 0; i < 5; i++) {
            NSLog(@"---3---%@", [NSThread currentThread]);
        }
    });
    
}

#pragma mark - 全局隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)globalSync {
    //全局隊列的優先級
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
    typedef long dispatch_queue_priority_t;
    
    // 1.獲取全局隊列 DISPATCH_QUEUE_PRIORITY_DEFAULT or 0 都可以
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 2.創建任務block
    typedef void (^TestBlock1)();
    TestBlock1 block1 = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // 3.給全局隊列globalQueue,添加同步任務dispatch_sync
    dispatch_sync(globalQueue, block1);
    dispatch_sync(globalQueue, block2);
    dispatch_sync(globalQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
    
}
#pragma mark - 全局隊列,異步任務: 開啟新線程,任務并發執行;
- (void)globalAsync {
    // 1.獲取全局隊列 DISPATCH_QUEUE_PRIORITY_DEFAULT or 0 都可以
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    // 2.創建任務
    typedef void (^TestBlock)();
    TestBlock block = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    // 3.全局隊列globalQueue,添加異步任務;
    dispatch_async(globalQueue, block);
    dispatch_async(globalQueue, block2);
    dispatch_async(globalQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---3---%@", [NSThread currentThread]);
        }
    });
}

#pragma mark - 串行隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)serialSync {
    char *queueName = "SerialQueue";
    // 串行隊列 DISPATCH_QUEUE_SERIAL or NULL
    dispatch_queue_t serialQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
    
    // 創建任務block
    typedef void (^TestBlock1)();
    TestBlock1 block1 = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // 給串行隊列serialQueue,添加同步任務dispatch_sync
    dispatch_sync(serialQueue, block1);
    dispatch_sync(serialQueue, block2);
    dispatch_sync(serialQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
    
}

#pragma mark - 串行隊列,異步任務: 開啟新線程,任務按添加順序依次執行;
- (void)serialAsync {
    // 1.創建隊列queue
    char *queueName = "SerialQueue";
    dispatch_queue_t serialQueue = dispatch_queue_create(queueName, NULL);
    
    // 2.創建任務block
    typedef void (^TestBlock1)();
    TestBlock1 block1 = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // 3.串行隊列serialQueue, 添加異步任務
    dispatch_async(serialQueue, block1);
    dispatch_async(serialQueue, block2);
    dispatch_async(serialQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
}

#pragma mark - 主隊列, 同步任務: 死鎖
- (void)mainSync {
    NSLog(@"%s", "主隊列mai zhuduilie, 同步任務sync tongburenwu, 會造成死鎖 huizaochengsisuo");
    // 1.獲得主隊列main
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    // 2.創建任務block
    typedef void (^TestBlock1)();
    TestBlock1 block1 = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // 3.給主隊列mainQueue,添加同步任務dispatch_sync
    dispatch_sync(mainQueue, block1);
    dispatch_sync(mainQueue, block2);
    dispatch_sync(mainQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
    // 死鎖導致block中的內容都不會執行
}

/*
 GCD Queue 分為三種:
 1,The main queue:主隊列,主線程就是在個隊列中。
 2,Global queues: 全局并發隊列。
 3,用戶隊列:是用函數 dispatch_queue_create 創建的自定義隊列
 
 dispatch_sync 和 dispatch_async 區別:
 dispatch_async(queue,block) async 異步隊列,dispatch_async 函數會立即返回, block會在后臺異步執行。
 dispatch_sync(queue,block) sync 同步隊列,dispatch_sync 函數不會立即返回,及阻塞當前線程,等待block同步執行完成。
 
 分析:
 在主線程中,即dispatch_get_main_queue()中,執行到sync時向dispatch_get_main_queue()插入同步block1.
 sync會等到后面block1執行完成才返回,sync又在dispatch_get_main_queue() 隊列中,它是串行隊列,sync是后加入的,
 前一個是主線程,所以sync想執行block必須等待主線程執行完成,主線程等待sync返回,去執行后續內容。
 造成死鎖,sync等待main執行完成,mian等待sync函數返回。
 */

#pragma mark - 主隊列,異步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)mainAsync {
    // 1.獲取主隊列main
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    // 2.創建任務block
    typedef void (^TestBlock1)();
    TestBlock1 block1 = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block1---%@", [NSThread currentThread]);
        }
    };
    void (^block2)() = ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block2---%@", [NSThread currentThread]);
        }
    };
    
    // 3.給主隊列mainQueue,添加異步任務dispatch_async
    dispatch_async(mainQueue, block1);
    dispatch_async(mainQueue, block2);
    dispatch_async(mainQueue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"---block--3---%@", [NSThread currentThread]);
        }
    });
}

#pragma mark -
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    /***********************************************************/
    // 定義block的兩種方式之一:
    // 定義
    // 參考范例,返回值int,參數(int, int)(沒有參數名,匿名),名稱Test
    typedef int (^Test1)(int, int);
    // 使用Test初始化一個變量test
    Test1 test1 ;
    // 實現
    test1 = ^(int x, int y) {
        return  x + y;
    };
    // 調用
    int result = test1(1, 2); //result = 3;
    NSLog(@"%d", result);
    
    /////////
    
    // 初始化變量,實現,同時進行
    Test1 test = ^(int x, int y) {
        return  x + y;
    };
    // 調用
    NSLog(@"%d", test(100, 200));
    
    /***********************************************************/
    // 定義block的兩種方式之二:
    // 定義,實現,合并進行
    // 直接定義一個變量test2,參數(int, int)(沒有參數名,匿名),名稱Test
    int (^test2)(int, int) = ^(int x, int y){
        return x + y;
    };
    NSLog(@"%d", test2(10, 20)); //result = 30;
    /***********************************************************/
}

Swift 3.0:

/**
 GCD:Grand Central Dispatch 牛X的中樞調度器
 GCD:自動管理線程的生命周期,(創建, 調度任務, 銷毀線程)
 
 任務:閉包closure or DispatchWorkItem
 隊列:DispatchQueue
 
 GCD自動從隊列中取出任務執行,遵循FIFO原則,先進先出
 
 任務執行方式:
    同步(synchronous ['s??kr?n?s]):不能開新線程
        DispatchQueue.global().sync {
            // 同步執行
        }
    異步(asynchronous [e's??kr?n?s]):能開新線程
        DispatchQueue.global().async {
            // code
            DispatchQueue.main.async {
                // 主線程中
            }
        }
 
 隊列DispatchQueue:
    DispatchQueue的默認初始化方法創建的就是一個串行隊列,如果要創建并發的隊列,在attributes中聲明concurrent。
    label:表示該隊列的名字(標識);
    attributes:表示隊列屬性,默認為串行,
    同步隊列
        let serialQueue = DispatchQueue(label: "QueueName")
        讓任務順序執行;
    主隊列
        let mainQueue = DispatchQueue.main
 
    并發隊列
        let concurrentQueue = DispatchQueue(label: "QueueName", attributes: .concurrent)
        讓多個任務并發執行,自動開啟多個線程同時執行任務;
    全局并發隊列
        let globalQueue = DispatchQueue.global(qos: .default)
        let globalQueue = DispatchQueue.global()
        // global 有默認的參數default, 如需改變優先級,則輸入對應的枚舉即可
 
 */
相關練習:
    // MARK: - 并發Concurrent,同步sync,沒有開啟新線程,任務在主隊列main依次執行;
    func concurrentSync() -> Void {
        // 創建并發隊列
        let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)
        
        // 任務類型
        typealias Task = () -> Void
        // Task類型的變量
        let task1: Task
        // 任務實現
        task1 = {
            print("concurrentSync task1...", Thread.current)
        }
        
        let task2: () -> Void = {
            print("concurrentSync task2...", Thread.current)
        }
        
        // 并發隊列Concurrent,同步sync執行
        concurrentQueue.sync(execute: task1) // main
        concurrentQueue.sync(execute: task2) // main
        concurrentQueue.sync {
            print("concurrentSync task3...", Thread.current)
        } // main
    }
    
    // MARK: - 并發Concurrent,異步async,開啟新線程,任務并發執行;
    func concurrentAsync() -> Void {
        // 隊列(并發concurrent)
        let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)
        // 任務(閉包 or block)
        typealias Task = () -> Void
        let task1: Task = {
            print("concurrentAsync-task1...", Thread.current)
        }
        let task2: () -> Void = {
            print("concurrentAsync-task2...", Thread.current)
        }
        // 并發,異步
        concurrentQueue.async(execute: task1) // new 1
        concurrentQueue.async(execute: task2) // new 2
        concurrentQueue.async {
            print("concurrentAsync-task3...", Thread.current)
        } // new 3
    }
    
    // MARK: - 全局global,同步sync,沒有開啟新線程,任務在主隊列main依次執行;
    func globalSync() -> Void {
        typealias Task = () -> Void
        let task1: Task = {
            print("globalSync...task1...", Thread.current)
        }
        let task2: () -> Void = {
            print("globalSync...task2...", Thread.current)
        }
        
        /**
         * global優先級的新舊枚舉值對應
         * DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated
         * DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default
         * DISPATCH_QUEUE_PRIORITY_LOW:          .utility
         * DISPATCH_QUEUE_PRIORITY_BACKGROUND:   .background
         */
        // public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue
        // global 有默認的參數default, 如需改變優先級,則輸入對應的枚舉即可
        DispatchQueue.global(qos: .userInteractive).sync(execute: task1) // main 1
        DispatchQueue.global(qos: .userInteractive).sync(execute: task2) // main 2
        DispatchQueue.global(qos: .userInteractive).sync {
            print("globalSync...task3...", Thread.current)
            
        } // main 3
    }
    
    // MARK: - 全局global,異步async,開啟新線程,任務并發執行;
    func globalAsync() -> Void {
        typealias Task = () -> Void
        let task1: Task = {
            print("globalAsync...task1...", Thread.current)
        }
        let task2: Task = {
            print("globalAsync...task2...", Thread.current)
        }
        DispatchQueue.global().async(execute: task1) // new 1
        DispatchQueue.global().async(execute: task2) // new 2
        DispatchQueue.global().async {
            print("globalAsync...task3...", Thread.current)
        } // new 3
    }
    
    /// 線程任務
    typealias ThreadTask = () -> Void

    // MARK: - 串行serial,同步sync,沒有開啟新線程,任務按順序執行;
    func serialSync() -> Void {
        // 隊列
        let serialQueue = DispatchQueue(label: "SerialQueue")
        // 任務
        let task1: ThreadTask = {
            print("serialSync...task1...", Thread.current)
        }
        let task2: ThreadTask = {
            print("serialSync...task2...", Thread.current)
        }
        let task3: ThreadTask = {
            print("serialSync...task3...", Thread.current)
        }
        // 串行,同步
        serialQueue.sync(execute: task1) // main 1
        serialQueue.sync(execute: task2) // main 2
        serialQueue.sync(execute: task3) // main 3
    }
    
    // MARK: - 串行Serial,異步async,開啟新線程,任務按順序執行
    func serialAsync() -> Void {
        // 隊列
        let serialQueue = DispatchQueue(label: "SerialQueue")
        // 任務
        let task1: ThreadTask = {
            print("serialSync...task1...", Thread.current)
        }
        let task2: ThreadTask = {
            print("serialSync...task2...", Thread.current)
        }
        let task3: ThreadTask = {
            print("serialSync...task3...", Thread.current)
        }
        // 串行,異步
        serialQueue.async(execute: task1) // new 1
        serialQueue.async(execute: task2) // new 2
        serialQueue.async(execute: task3) // new 3
    }
    
    // MARK: - 主隊列main,同步sync,死鎖
    func mainSync() -> Void {
        // 隊列
        let mainQueue = DispatchQueue.main
        // 任務
        let task1: ThreadTask = {
            print("serialSync...task1...", Thread.current)
        }
        let task2: ThreadTask = {
            print("serialSync...task2...", Thread.current)
        }
        let task3: ThreadTask = {
            print("serialSync...task3...", Thread.current)
        }
        // 主隊列,同步
        mainQueue.sync(execute: task1) // 死鎖 x
        mainQueue.sync(execute: task2) // x
        DispatchQueue.main.sync(execute: task3) // x
    }
    
    // MARK: - 主隊列main,異步async,不開啟新線程,任務依次執行
    func mainAsync() -> Void {
        let mainQueue = DispatchQueue.main
        
        let task1: ThreadTask = {
            print("serialSync...task1...", Thread.current)
        }
        let task2: ThreadTask = {
            print("serialSync...task2...", Thread.current)
        }
        let task3: ThreadTask = {
            print("serialSync...task3...", Thread.current)
        }
        
        mainQueue.async(execute: task1) // main 1
        mainQueue.async(execute: task2) // main 2
        DispatchQueue.main.async(execute: task3) // main 3
    }
    
    // MARK: - 閉包測試
    func closureTest() -> Void {
        // 閉包回顧
        /***********************************************************/
        // 定義, 有3+參, 有返回值
        typealias Test = (Int, Int, Int) -> Int
        // 聲明變量test1
        var test1: Test
        // 實現
        test1 = { x, y, z in
            // 閉包中的操作
            print("有3+參, 有返回值 test1...111")
            return x + y + z
        }
        // 調用
        print("test1...", test1(1, 2, 3))
        
        // 聲明,實現
        let test2: Test = {
            // 閉包中的操作
            print("有3+參, 有返回值 test2...222")
            return $0 + $1 + $2
        }
        // 調用
        print("test2...", test2(10, 20, 30))
        /***********************************************************/
        // 定義, 有2參, 有返回值
        var test3: (Int, Int) -> Int
        // 實現
        test3 = (+)
        // 調用
        print("有2參, 有返回值 test3...", test3(100, 200))
        /***********************************************************/
        // 定義,無參,有返回值
        var test4: () -> Int
        // 實現
        test4 = {
            // 閉包中的操作
            print("無參,有返回值 test4... 444")
            return 12345
        }
        // 調用
        print("test4...", test4())
        /***********************************************************/
        // 定義,無參,無返回值
        let test5: () -> Void = {
            // 相關操作
            print("無參,有返回值 test5... 555")
        }
        test5()
        /***********************************************************/
    }

參考資料:
http://www.lxweimin.com/p/fc78dab5736f
http://www.lxweimin.com/p/28044b17f94b
https://www.logcg.com/archives/2040.html
https://github.com/future-challenger/Swift3.0/blob/master/GCD/README.md
https://my.oschina.net/doxing/blog/618132
http://v.youku.com/v_show/id_XMTU5MDg1MTE0NA==.html
http://v.youku.com/v_show/id_XMTU5MDg0OTY1Mg==.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容

  • GCD GCD的全稱是Grand Central Dispatch,字面意思就是“極好的中樞調度器”,它能通過隊列...
    cr7aa閱讀 463評論 0 0
  • 1、前言 GCD的學習中一定要理解任務,同步、異步,串行、并發的概念,以及他們之間相互結合運行的效果。 2、GCD...
    SuperDawn_0828閱讀 367評論 0 1
  • 許久許久未見的人 原來真的夢不到 孤獨 和誰的相處都無法避免 可能就是某個時刻的無解和涼意 這很平常呀 所以不 過...
    寫在沙上閱讀 214評論 0 0
  • Eimon閱讀 178評論 0 0
  • 再見你時,一如從前的模樣。光潔的額頭,姣好的面容,笑時露出一排整齊的牙齒。和年少時分毫未變。 走進你的房...
    土lemon閱讀 670評論 0 2