iOS多线程-GCD

很久前的总结,今天贴出来。适合看了就用,很少讲解,纯粹用法。

目录

Dispatch Queue

dispatch_queue_create

系统标准提供的Dispatch Queue

dispatch_set_target_queue

dispatch_after

Dispatch Group

dispatch_barrier_async

dispatch_sync

dispatch_apply

dispatch_suspend和dispatch_resume

Dispatch Semaphore

dispatch_once



Dsipatch Queue

官方说明:开发者要做的只是定义想要执行的任务并追加到适当的Dispatch Queue中。

    这句话用如下代码表示:

    dispatch_async(queue, ^{//想要执行的任务});

    即:使用block“定义想要执行的任务”,通过dispatch_async函数“追加”到赋值在queue的“Dispatch Queue”中,这样既可使指定的block在另一线程中运行。


简介:Dispatch Queue 是执行处理的等待队列。通过dispatch_async函数等API,在block中记述想要执行的处理并将其追加到Dispatch Queue中。Dispatch Queue按照追加的顺序执行处理。

分类:

    Serial Dispatch Queue:等待现在执行中的处理。

    Concurrent Dispatch Queue:不等待现在执行中的处理。

比较:

    Serial Dispatch Queue:因为等待现在执行中的处理结束,所以后一个等待前一个处理执行结束后才开始执行,同时执行的处理数只有一个。

    Concurrent Dispatch Queue:因为不等待现在执行中的处理结束,所以由前到后依次开始执行,即并发(使用多个线程同时)执行多个处理。注:并发执行的处理数取决于当前系统的状态。

附:

iOS和OSX的核心一一XNU内核决定应当使用的线程数,并只生成所需的线程执行处理。另外,当执行结束,应当执行的处理减少时,XNU内核会结束不再需要的线程。XNU内核仅使用Concurrent Dispatch Queue 便可完美的管理并执行多个处理的线程。



dispatch_queue_create

//虽然Serial Dispatch Queue和Concurrent Dispatch Queue受到系统资源的限制,但用dispatch_queue_create函数可生成任意多个Dispatch Queue。

    //在一个Serial Dispatch Queue中同时只能执行一个追加处理,多个Serial Dispatch Queue可并行执行

    //过多使用Serial Dispatch Queue,会消耗大量内存,引起大量上下文切换,大幅度降低系统的响应性能,因此注意Serial Dispatch Queue的生成个数。

    //Concurrent Dispatch Queue不管生成多少,由于XNU内核只使用有效管理的线程,因此不会发生Serial Dispatch Queue的问题。

    //多个线程更新相同资源导致的数据竞问题,使用Serial Dispatch Queue。

    //当并行执行不发生数据竞争等问题的处理时,使用Concurrent Dispatch Queue。


    //通过dispatch_queue_create可生成Dispatch Queue,注意,生成的Dispatch Queue在使用结束后必须由程序员进行释放(现在GCD对象已经纳入了ARC的管理范围,在纳入之前是需要程序员按照内存管理的思考方式来手动管理GCD对象的)。

    dispatch_queue_t serialDispatchQueue = dispatch_queue_create("Dispatch Queue的名称", NULL);

    //参数1:Dispatch Queue的名称,可设NULL

    //参数2:指定Dispatch Queue的类型。若为NULL,则为Serial Dispatch Queue;若为DISPATCH_QUEUE_CONCURRENT,则为Concurrent Dispatch Queue

    //返回值:表示Dispatch Queue的diapatch_queue_t类型


    //通过dispatch_release函数释放

    //dispatch_release(serialDispatchQueue);


    //通过dispatch_retain函数持有

    //dispatch_retain(serialDispatchQueue);


    //通过dispatch_async函数将block中定义的处理“追加”到赋值在serialDispatchQueue的“Dispatch Queue”中

    dispatch_async(serialDispatchQueue, ^{

        NSLog(@"//被追加的定义处理的block");

    });

    //注意,在dispatch_async函数中追加Block到Dispatch Queue,该Block通过dispatch_retain函数持有Dispatch Queue。无论Dispatch Queue是Serial Dispatch Queue还是Concurrent Dispatch Queue都一样。一旦Block执行结束,就通过dispatch_release函数释放该Block持有的Dispatch Queue。



系统标准提供的Dispatch Queue

//Main Dispatch Queue,是在主线程中执行的Dispatch Queue。Main Dispatch Queue是Serial Dispatch Queue。追加到Main Dispatch Queue的处理在主线程的RunLoop中执行。由于Main Dispatch Queue在主线程中执行,因此要将用户界面的界面更新等一些必须在主线程中执行的处理追加到Main Dispatch Queue使用。

    //Global Dispatch Queue,是所有的应用程序都能够使用的Concurrent Dispatch Queue。没有必要通过dispatch_queue_create函数逐个生成Concurrent Dispatch Queue。只要获取Global Dispatch Queue即可。Global Dispatch Queue有4个执行优先级,分别是高优先级(High Priority)、默认优先级(Default Priority)、低优先级(Low Priority)和后台优先级(Background Priority)。用于Global Dispatch Queue的线程的执行优先级,使用Global Dispatch Queue的执行优先级。线程的执行优先级不能保证实时性,只是大致的判断。


    //Main Dispatch Queue的获取方法

    dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();

    //Global Dispatch Queue(高优先级)的获取方法

    dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    //Global Dispatch Queue(默认优先级)的获取方法

    dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //Global Dispatch Queue(低优先级)的获取方法

    dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW , 0);

    //Global Dispatch Queue(后台优先级)的获取方法

    dispatch_queue_t globalDispatchQueueBackgroud = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND , 0);


    //另外,对于Main Dispatch Queue和Global Dispatch Queue执行dispatch_release函数和dispatch和_retain函数不会引起任何变化,也不会有任何问题。但为了符合内存管理的思考方式,可以直接对Main Dispatch Queue和Global Dispatch Queue执行dispatch_release函数和dispatch和_retain函数。



dispatch_set_target_queue

//dispatch_queue_create函数生成的Dispatch Queue不管是Serial Dispatch Queue还是Concurrent Dispatch Queue,都使用与默认优先级Global Dispatch Queue相同执行优先级的线程。


    //通过dispatch_set_target_queue函数变更生成的Dispatch Queue的优先级。

    dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("Dispatch Queue的名称", NULL);

    dispatch_queue_t globalDispatchQueueBackgroud = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND , 0);

    dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackgroud);

    //参数1:指定要变更执行优先级的Dispatch Queue

    //参数2:指定与要变更为的执行优先级相同的Dispatch Queue,即目标。

    //注:第一个参数不能指定为系统标准提供的Dispatch Queue。


    //通过dispatch_set_target_queue防止处理并行执行

    //如果在多个Serial Dispatch Queue中用dispatch_set_target_queue函数指定目标为某一个Serial Dispatch Queue,那么原先本应并行执行的多个Serial Dispatch Queue,在目标Serial Dispatch Queue上只能同时执行一个处理。



dispatch_after

//想在指定时间后执行处理的情况,可使用dispatch_after函数来实现。

    //dispatch_after函数并不是在指定的时间后执行处理,而只是在指定的时间追加处理到Dispatch Queue。


    //通过dispatch_after在3秒后将指定的block追加到Main Dispatch Queue

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);

    dispatch_after(time, dispatch_get_main_queue(), ^{

        NSLog(@"1秒后");

    });

    //参数1:指定时间用的dispatch_time_t类型的值,该值使用dispatch_time函数或dispatch_walltime函数作成。

    //参数2:指定要追加处理的Dispatch Queue

    //参数3:指定记述要执行处理的Block

    //注:因为Main Dispatch Queue在主线程的RunLoop中执行,所以在比如每隔1/60秒执行的RunLoop中,Block最快在3秒后执行,最慢在3秒+1/60秒后执行,并且在Main Dispatch Queue有大量处理追加或主线程的处理本身有延迟时,这个时间会更长。虽然在有严格时间的要求下使用时会出现问题,但在想大致延迟执行处理时,该函数是非常有效的。


    //dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);

    //dispatch_time函数能够获取从第一个参数dispatch_time_t类型值中指定的时间开始,到第二个参数指定的毫微秒单位时间后的时间。DISPATCH_TIME_NOW表示现在的时间。第二个参数中用秒和NSEC_PER_SEC的相乘来表示,毫秒和NSEC_PER_MSEC相乘来表示。ull即unsigned long long


    //dispatch_walltime函数用于计算绝对时间,如某个具体的时间。而dispatch_time通常用于计算相对时间。



Dispatch Group

//在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理时:

    //a.只使用一个Serial Dispatch Queue时,只要将想执行的处理全部追加到该 Serial Dispatch Queue中并在最后追加结束处理,即可实现。

    //b.使用Concurrent Dispatch Queue时或同时使用多个Dispatch Queue时,可通过Dispatch Group实现。

    //无论向什么样的Dispatch Queue中追加处理,使用Dispatch Group都可监视这些处理执行的结果。一旦检测到所有处理执行结束,就可将结束的处理追加到Dispatch Queue中。


    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);


    //通过dispatch_group_create函数生成Dispatch Group,注意,生成的Dispatch Group在使用结束后必须通过dispatch_release释放(现在GCD对象已经纳入了ARC的管理范围,在纳入之前是需要程序员按照内存管理的思考方式来手动管理GCD对象的),同Dispatch Queue。

    dispatch_group_t group = dispatch_group_create();


    //通过dispatch_group_async函数追加block到指定的Dispatch Queue中,第一个参数为监视的Dispatch Group。

    //注:与追加Block到Dispatch Queue时同样,Block通过dispatch_retain函数持有Dispatch Group,如果Block执行结束,该Block就通过dispatch_release函数释放持有的Dispatch Group。一旦Dispatch Group使用结束,不用考虑属于该Dispatch Group的Block,立即通过dispatch_release函数释放即可。

    dispatch_group_async(group, queue, ^{

        NSLog(@"blk0");

    });

    dispatch_group_async(group, queue, ^{

        NSLog(@"blk1");

    });

    dispatch_group_async(group, queue, ^{

        NSLog(@"blk2");

    });


    //通过dispatch_group_notify函数,在追加到Dispatch Queue中(即被Dispatch Group监测)的处理全部执行结束时,会将执行结束处理的Block追加到Dispatch Queue中

    //参数1:指定为要监视的Dispatch Group。

    //参数2:指定要追加到的Dispatch Queue。

    //参数3:结束处理的block

    dispatch_group_notify(group, queue, ^{

        NSLog(@"结束处理");

    });


    //也可以使用dispatch_group_wait函数仅等待全部处理执行结束

    //等待:意味着一旦调用dispatch_group_wait函数,该函数就处于调用的状态而不返回。执行dispatch_group_wait函数的现在的线程(当前线程)停止。在经过dispatch_group_wait函数中指定的时间或属于指定Dispatch Group的处理全部执行结束之前,执行该函数的线程停止。

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    //参数1:指定Dispatch Group

    //参数2:指定最多等待的时间(超时),dispatch_time_t类型值

    //返回值:若等待的全部处理执行结束,返回0。否则,返回不为0。


    //当参数2为指定等待1秒时:

    dispatch_time_t time2 = dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);

    long result = dispatch_group_wait(group, time2);


    if (result == 0) {

        //若全部处理执行结束,返回值为0

    }else{

        //若超时,即还有处理在执行,则返回值不为0

    }

    //当参数2为DISPATCH_TIME_FORVER,意味着永久等待。只要属于Dispatch Group的处理尚未执行结束,就会一直等待,中途不能取消。因此dispatch_group_wait函数返回时,由于属于Dispatch Group的处理必定全部执行结束,因此返回值为0。

    //当参数2为DISPATCH_TIME_NOW,则不用任何等待即可判定属于Dispatch Group的处理是否执行结束



dispatch_barrier_async

//写入处理不可以与写入处理和读取处理并行执行。读取处理与读取处理可并行执行


    //为了高效率的进行访问:

    //读取处理追加到Concurrent Dispatch Queue中,写入处理在任一个读取处理没有执行的状态下,追加到Serial Dispatch Queue中即可,在写入处理结束之前,读取处理不可执行。

    //通过dispatch_barrier_async也可实现

    dispatch_queue_t queue = dispatch_queue_create("Dispatch Queue的名称", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{/*读取处理0*/});

    dispatch_async(queue, ^{/*读取处理1*/});

    dispatch_async(queue, ^{/*读取处理2*/});

    dispatch_async(queue, ^{/*读取处理3*/});

    //写入处理,之后会对写入的内容进行读取处理


  //若简单的在dispatch_async函数中加入写入处理,那么根据Concurrent Dispatch Queue的性质,就有可能在追加到写入处理前面的处理中读取到与期待不符的数据,还可能因非法访问导致应用程序异常结束。如果追加多个写入处理,则可能发生更多问题,比如数据竞争。

    //通过dispatch_barrier_async函数会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束之后,再将指定的处理(异步)追加到该Concurrent Dispatch Queue中。然后在由dispatch_barrier_async函数追加的处理执行完毕后,Concurrent Dispatch Queue才恢复为一般的动作,追加到该Concurrent Dispatch Queue的处理又开始并行执行。

    dispatch_barrier_async(queue, ^{/*写入处理*/});


    dispatch_async(queue, ^{/*读取处理4*/});

    dispatch_async(queue, ^{/*读取处理5*/});

    dispatch_async(queue, ^{/*读取处理6*/});

    dispatch_async(queue, ^{/*读取处理7*/});


    //dispatch_barrier_sync函数与dispatch_barrier_async不同的地方是它会将指定的block同步追加到Concurrent Dispatch Queue中。在追加Block结束之前,dispatch_barrier_sync函数会一直等待。即dispatch_barrier_async不阻塞当前线程,dispatch_barrier_sync阻塞当前线程。

参考资料:http://blog.csdn.net/u013046795/article/details/47057585



dispatch_sync

//dispatch_async函数将指定的Block"非同步"的追加到指定的Dispatch Queue中,dispatch_async函数不作任何等待。


    //dispatch_sync函数将指定的Block"同步"追加到指定的Dispatch Queue中。在追加Block结束之前,dispatch_sync函数会一直等待。即一旦调用dispatch_sync函数,那么在指定的处理执行结束之前,该函数不会返回。


    //dispatch_sync函数出现的死锁问题:

    //a.该源代码在Main Dispatch Queue即主线程中执行指定的Block,并等待其执行结束。而其实主线程中正在执行这些源代码,所以无法执行追加到Main Dispatch Queue 的Block。

    dispatch_queue_t queue = dispatch_get_main_queue();

    dispatch_sync(queue, ^{

        NSLog(@"hello");

    });

    //b.Main Dispatch Queue中执行的Block等待Main Dispatch Queue中要执行的Block执行结束

    dispatch_queue_t queue2 = dispatch_get_main_queue();

    dispatch_async(queue2, ^{

        dispatch_sync(queue2,^{

            NSLog(@"hello");

        });

    });

    //c.Serial Dispatch Queue 也会引起相同的问题

    dispatch_queue_t queue3 = dispatch_queue_create("Dispatch Queue的名称", NULL);

    dispatch_async(queue3, ^{

        dispatch_sync(queue3, ^{

            NSLog(@"hello");

        });

    });



dispatch_apply

//dispatch_apply函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待追加的全部处理执行结束。

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_apply(10, queue, ^(size_t index) {

        NSLog(@"%zu",index);

    });

    NSLog(@"done");

    //参数1:重复次数

    //参数2:指定要追加处理的Dispatch Queue

    //参数3:指定记述要执行处理的Block

    //注,参数3为带有参数的block,这是为了按第一个参数重复追加Block并区分各个Block而使用


    //建议:由于dispatch_apply函数也与dispatch_sync函数相同,会等待处理执行结束,因此推荐在dispatch_async函数中非同步地执行dispatch_apply函数。

    dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(queue2, ^{

        dispatch_apply(10, queue2, ^(size_t index) {

            NSLog(@"%zu",index);

        });

        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"done");

        });

    });



dispatch_suspend和dispatch_resume

dispatch_queue_t queue = dispatch_queue_create("Dispatch Queue的名称", NULL);


    //dispatch_suspend函数挂起指定的Dispatch Queue。

    dispatch_suspend(queue);

    //挂起后,追加到Dispatch Queue中但尚未执行的处理在此之后停止执行。


    //dispatch_resume函数恢复指定的Dispatch Queue。

    dispatch_resume(queue);

    //恢复则使得这些处理(追加到Dispatch Queue中但尚未执行的处理)能够继续执行。


    //注,这些函数对已经执行的处理没有影响。



Dispatch Semaphore

//Dispatch Semaphore是持有计数的信号。计数为0时等待,计数为1或大于1时,减去1而不等待。


    //通过dispatch_semaphore_create函数生成Dispatch Semaphore。注意,生成的Dispatch Semaphore在使用结束后必须由程序员进行释放(现在GCD对象已经纳入了ARC的管理范围,在纳入之前是需要程序员按照内存管理的思考方式来手动管理GCD对象的),同Dispatch Queue。

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

    //参数1:表示计数的初始值。本例将计数值初始化为"1"。


    //通过dispatch_semaphore_wait函数等待Dispatch Semaphore的计数值大于或等于1。当计数值大于等于1,或者在待机中计数值大于等于1时,对该计数进行减法并从dispatch_semaphore_wait函数返回。

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    //参数1:等待的Dispatch Semaphore

    //参数2:与dispatch_group_wait函数等相同,指最多等待的时间(超时)。

    //返回:若计数值大于等于1,返回值为0。否则,返回值不为0。


    //通过返回值进行分支处理

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull*NSEC_PER_SEC);

    long result = dispatch_semaphore_wait(semaphore, time);

    if (result == 0) {

        /*

        *  Dispatch Semaphore 的计数值达到大于等于1

        *  或者在待机中的指定时间内Dispatch Semaphore的计数值达到大于等于1

        *  Dispatch Semaphore 的计数值减去1

        */

    }else{

        /*

        *  Dispatch Semaphore 的计数值为0

        */

    }


    //实际应用的例子

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //生成Dispatch Semaphore,Dispatch Semaphore的计数初始值设定为"1",保证可访问NSMutableArray类对象的线程同时只能有一个。

    dispatch_semaphore_t semaphore2 = dispatch_semaphore_create(1);

    NSMutableArray *array = [[NSMutableArray alloc]init];


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

        dispatch_async(queue, ^{

            //等待Dispatch Semaphore的计数值达到大于等于1时,将Dispatch Semaphore的计数值减去1

            dispatch_semaphore_wait(semaphore2, DISPATCH_TIME_FOREVER);

            //执行到此时的Dispatch Semaphore的计数值恒为"0",即其它线程处于等待状态,所以可访问NSMutableArray类对象的线程只有1个,因此可安全的进行更新

            [array addObject:[NSNumber numberWithInt:i]];

            //通过dispatch_semaphore_signal函数将Dispatch Semaphore的计数值加1

            dispatch_semaphore_signal(semaphore2);

            //之后,如果有其它通过dispatch_semaphore_wait函数等待Dispatch Semaphore的计数值大于等于1的线程,就由最先等待的线程执行

        });

    }



dispatch_once

//dispatch_once函数是保证在应用程序中只执行一次指定处理的API,比如初始化。


    //使用是否初始化的标志变量来判断是否初始化

    static  int initialized = NO;

    if (initialized == NO) {

        //初始化处理

        initialized = YES;

    }

    //在大多数情况这种方式下是安全的。但是在多核CPU中,在正在更新表示是否初始化的标志变量时读取,就有可能多次执行初始化处理


    //使用dispatch_once函数

    static dispatch_once_t pred;

    dispatch_once (&pred,^{

        //初始化处理

    });

    //dispatch_once函数即使在多线程环境下执行,也可保证百分比安全。



GCDAsyncSocket快速开发Socket通信

参考:http://blog.csdn.net/bianhuanshizhe/article/details/69426022



如有转载,请说明原处

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • GCD (Grand Central Dispatch) :iOS4 开始引入,使用更加方便,程序员只需要将任务添...
    池鹏程阅读 1,326评论 0 2
  • iOS多线程之GCD 什么是GCD GCD(grand central dispatch) 是 libdispat...
    comst阅读 1,200评论 0 0
  • 多线程概念 线程线程指的是:1个CPU执行的CPU命令列为一条无分叉路径 多线程这种无分叉路径不止一条,存在多条即...
    我系哆啦阅读 576评论 0 5
  • 1. GCD简介 什么是GCD呢?我们先来看看百度百科的解释简单了解下概念 引自百度百科:Grand Centra...
    千寻_544f阅读 362评论 0 0
  • 选择一个城市,便是选择了一种生活。 北上广,都市繁华,人才熙攘,有着无限的机会和可能。无数人带着激情与热血,来到这...
    晚风中Sharon阅读 473评论 7 8