iOS多线程(3)-GCD

  • 简介:

    为什么要用 GCD 呢?因为 GCD 有很多好处啊,具体如下:
    GCD 可用于多核的并行运算
    GCD 会自动利用更多的 CPU 内核(比如双核、四核)
    GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码
    既然 GCD 有这么多的好处,那么下面我们就来系统的学习一下 GCD 的使用方法。

目录:

  • 队列创建

  • 同步异步

  • 线程间通讯

  • 延迟执行(dispatch_after)

  • 定时器(dispatch_timer)

  • 一次执行(dispatch_once)

  • 迭代(dispatch_apply)

  • 队列组(dispatch_group_notify)

  • 等待(dispatch_group_wait)

  • 信号(dispatch_semaphore_t)

  • 并发控制通过信号实现

  • 队列创建:
    //串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL);
    //并行队列
    dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT);
    //全局并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //主线程队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
  • 同步异步:
    - (void)asyncAction {
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_async(queue, ^{
          NSLog(@"async---%@",[NSThread currentThread]);
      });
    }
    
    - (void)syncAction {
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_sync(queue, ^{
          NSLog(@"sync---%@",[NSThread currentThread]);
      });
    }
    
    输出:
    ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)}
    ---<NSThread: 0x60000007f300>{number = 1, name = main}
    
  • 线程间通讯:
    - (void)asyncToSyncAction {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          NSLog(@"---%@",[NSThread currentThread]);
          
          // 回到主线程
          dispatch_async(dispatch_get_main_queue(), ^{
              NSLog(@"---%@",[NSThread currentThread]);
          });
      });
    }
    
    输出:
    ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)}
    ---<NSThread: 0x60000007f300>{number = 1, name = main}
    
  • 栅栏(dispatch_barrier_async):
    - (void)barrierAction {
        dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT);
      
        for (int i = 0; i < 10; i ++) {
            dispatch_async(queue, ^{
                [NSThread sleepForTimeInterval:2];
                NSLog(@"1---%@",[NSThread currentThread]);
            });
        }
      
        //barrier
        dispatch_barrier_async(queue, ^{
            [NSThread sleepForTimeInterval:2];
            NSLog(@"[Barrier: ---%@",[NSThread currentThread]);
        });
    
        for (int i = 0; i < 10; i ++) {
            dispatch_async(queue, ^{
                [NSThread sleepForTimeInterval:2];
                NSLog(@"3---%@",[NSThread currentThread]);
            });
        }
    }
    
    输出:
    2018-03-20 17:57:39.417137+0800 GCD[55856:2568834] 1---<NSThread: 0x604000074780>{number = 6, name = (null)}
    2018-03-20 17:57:39.417137+0800 GCD[55856:2568833] 1---<NSThread:   0x6000002701c0>{number = 3, name = (null)}
    2018-03-20 17:57:39.417138+0800 GCD[55856:2568832] 1---<NSThread: 0x60c00007e7c0>{number = 4, name = (null)}
    2018-03-20 17:57:39.417148+0800 GCD[55856:2568835] 1---<NSThread: 0x60800007d7c0>{number = 5, name = (null)}
    2018-03-20 17:57:39.417197+0800 GCD[55856:2568853] 1---<NSThread: 0x600000270080>{number = 7, name = (null)}
    2018-03-20 17:57:39.417247+0800 GCD[55856:2568855] 1---<NSThread: 0x6040000754c0>{number = 8, name = (null)}
    2018-03-20 17:57:39.417308+0800 GCD[55856:2568856] 1---<NSThread: 0x60000026fac0>{number = 10, name = (null)}
    2018-03-20 17:57:39.417329+0800 GCD[55856:2568854] 1---<NSThread: 0x604000074a80>{number = 9, name = (null)}
    2018-03-20 17:57:39.417344+0800 GCD[55856:2568857] 1---<NSThread: 0x604000074380>{number = 11, name = (null)}
    2018-03-20 17:57:39.417361+0800 GCD[55856:2568858] 1---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
    2018-03-20 17:57:41.420468+0800 GCD[55856:2568858] [Barrier: ---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
    2018-03-20 17:57:43.423862+0800 GCD[55856:2568858] 3---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
    2018-03-20 17:57:43.423827+0800 GCD[55856:2568855] 3---<NSThread: 0x6040000754c0>{number = 8, name = (null)}
    2018-03-20 17:57:43.423826+0800 GCD[55856:2568854] 3---<NSThread: 0x604000074a80>{number = 9, name = (null)}
    2018-03-20 17:57:43.423827+0800 GCD[55856:2568857] 3---<NSThread: 0x604000074380>{number = 11, name = (null)}
    2018-03-20 17:57:43.423855+0800 GCD[55856:2568853] 3---<NSThread: 0x600000270080>{number = 7, name = (null)}
    2018-03-20 17:57:43.423823+0800 GCD[55856:2568856] 3---<NSThread: 0x60000026fac0>{number = 10, name = (null)}
    2018-03-20 17:57:43.423949+0800 GCD[55856:2568834] 3---<NSThread: 0x604000074780>{number = 6, name = (null)}
    2018-03-20 17:57:43.423952+0800 GCD[55856:2568833] 3---<NSThread: 0x6000002701c0>{number = 3, name = (null)}
    2018-03-20 17:57:43.423960+0800 GCD[55856:2568835] 3---<NSThread: 0x60800007d7c0>{number = 5, name = (null)}
    2018-03-20 17:57:43.423964+0800 GCD[55856:2568832] 3---<NSThread: 0x60c00007e7c0>{number = 4, name = (null)}
    
  • 延迟执行(dispatch_after):
    - (void)afterAction {
      NSLog(@"[After]: begin currentThread---%@",[NSThread currentThread]);
      
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          NSLog(@"[After]: main ---%@",[NSThread currentThread]);
      });
      
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          NSLog(@"[After]: global ---%@",[NSThread currentThread]);
      });
    }
    
    输出:
    2018-03-20 18:01:33.749444+0800 GCD[55856:2568766] [After]: begin currentThread---<NSThread: 0x60000006e280>{number = 1, name = main}
    2018-03-20 18:01:35.928257+0800 GCD[55856:2568766] [After]: main ---<NSThread: 0x60000006e280>{number = 1, name = main}
    2018-03-20 18:01:35.928274+0800 GCD[55856:2571380] [After]: global ---<NSThread: 0x60c00007e280>{number = 13, name = (null)}
    
  • 定时器(dispatch_timer):
    @property(nonatomic,strong) dispatch_source_t tTimer;
    
    - (void)timerAction {
     NSLog(@"[Timer]: begin currentThread---%@",[NSThread currentThread]);
     
     if (!self.tTimer) {
         self.tTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
         NSLog(@"self.tTimer = %@",self.tTimer);
         dispatch_source_set_timer(self.tTimer,
                                   dispatch_walltime(NULL, 0 * NSEC_PER_SEC),
                                   0.32 * NSEC_PER_SEC,
                                   0);
         dispatch_source_set_event_handler(self.tTimer, ^{
             NSLog(@"1111");
         });
     
         dispatch_resume(self.tTimer);
     }
     else {
         dispatch_source_cancel(self.tTimer);
         self.tTimer = nil;
     }
     //        dispatch_suspend(self.tTimer);
     //        dispatch_source_cancel(self.tTimer);
     //        self.tTimer = nil; Crash
     
     //        dispatch_suspend(self.tTimer);
     //        self.tTimer = nil; Crash
    }
    
  • 一次执行(dispatch_once):
    - (void)onceAction {
      __block int index = 0;
      for (int i = 0; i < 10; i ++) {
          static dispatch_once_t onceToken;
          dispatch_once(&onceToken, ^{
              index ++;
              NSLog(@"[Once]:-------index = %d",index);
          });
      }
    }
    
    输出:
    2018-03-20 18:03:17.189632+0800 GCD[55856:2568766] [Once]:-------index = 1
    
  • 迭代(dispatch_apply):
    - (void)applyAction {
      //并行迭代
      dispatch_queue_t queue = dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      //串行队列迭代与for循环效果一样
      //queue = dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL);
      
      NSLog(@"apply---begin");
      dispatch_apply(6, queue, ^(size_t index) {
          NSLog(@"%zd---%@",index, [NSThread currentThread]);
          [NSThread sleepForTimeInterval:2];
      });
      NSLog(@"apply---end");
    }
    
    并行队列输出:
    2018-03-20 18:05:42.458703+0800 GCD[56041:2574450] apply---begin
    2018-03-20 18:05:42.459384+0800 GCD[56041:2574450] 0---<NSThread: 0x60c000262bc0>{number = 1, name = main}
    2018-03-20 18:05:42.459417+0800 GCD[56041:2574512] 1---<NSThread: 0x60c00027f840>{number = 3, name = (null)}
    2018-03-20 18:05:42.459504+0800 GCD[56041:2574499] 4---<NSThread: 0x6080002786c0>{number = 7, name = (null)}
    2018-03-20 18:05:42.459504+0800 GCD[56041:2574502] 3---<NSThread: 0x604000270e00>{number = 4, name = (null)}
    2018-03-20 18:05:42.459506+0800 GCD[56041:2574500] 5---<NSThread: 0x604000270c00>{number = 6, name = (null)}
    2018-03-20 18:05:42.459521+0800 GCD[56041:2574501] 2---<NSThread: 0x608000278a00>{number = 5, name = (null)}
    2018-03-20 18:05:44.463743+0800 GCD[56041:2574450] apply---end
    
    串行队列输出:
    2018-03-20 18:07:33.988048+0800 GCD[56083:2576141] apply---begin
    2018-03-20 18:07:33.988516+0800 GCD[56083:2576141] 0---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:35.989109+0800 GCD[56083:2576141] 1---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:37.990556+0800 GCD[56083:2576141] 2---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:39.992050+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:41.993583+0800 GCD[56083:2576141] 4---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:43.995163+0800 GCD[56083:2576141] 5---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:07:45.995811+0800 GCD[56083:2576141] apply---end
    
  • 队列组(dispatch_group_notify):
    - (void)groupNotifyAction {
      NSLog(@"group---begin");
      
      dispatch_group_t group = dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
      });
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"2---%@",[NSThread currentThread]);
      });
      
      dispatch_group_notify(group, [self mainQueue], ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"3---%@",[NSThread currentThread]);
          NSLog(@"group notify");
      });
    }
    
    输出:
    2018-03-20 18:09:47.306064+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:09:49.307609+0800 GCD[56083:2576199] 2---<NSThread: 0x60800006ce00>{number = 4, name = (null)}
    2018-03-20 18:09:49.307608+0800 GCD[56083:2577770] 1---<NSThread: 0x60400007fac0>{number = 3, name = (null)}
    2018-03-20 18:09:51.309380+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{number = 1, name = main}
    2018-03-20 18:09:51.309744+0800 GCD[56083:2576141] group notify
    
    - (void)groupNotify1Action {
      NSLog(@"group---begin");
      
      dispatch_group_t group = dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_enter(group);
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
          dispatch_group_leave(group);
      });
      
      dispatch_group_enter(group);
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:5];
          NSLog(@"2---%@",[NSThread currentThread]);
          dispatch_group_leave(group);
      });
      
      dispatch_group_notify(group, [self mainQueue], ^{
          NSLog(@"group notify : %@",[NSThread currentThread]);
      });
    }
    
    输出:
    2018-03-20 18:09:53.329762+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:09:55.332737+0800 GCD[56083:2576199] 1---<NSThread: 0x60800006ce00>{number = 4, name = (null)}
    2018-03-20 18:09:58.331259+0800 GCD[56083:2577770] 2---<NSThread: 0x60400007fac0>{number = 3, name = (null)}
    2018-03-20 18:09:58.331676+0800 GCD[56083:2576141] group notify : <NSThread: 0x60c000065740>{number = 1, name = main}
    
  • 等待(dispatch_group_wait):
    - (void)groupWaitAction {
      NSLog(@"group---begin");
      
      dispatch_group_t group =  dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
      });
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:5];
          NSLog(@"2---%@",[NSThread currentThread]);
      });
      
      dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
      
      NSLog(@"group---end");
    }
    
    输出:
    2018-03-20 18:12:57.523759+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:12:59.527048+0800 GCD[56083:2579780] 1---<NSThread: 0x600000260780>{number = 5, name = (null)}
    2018-03-20 18:13:02.524335+0800 GCD[56083:2577781] 2---<NSThread: 0x60000007fd40>{number = 6, name = (null)}
    2018-03-20 18:13:02.524954+0800 GCD[56083:2576141] group---end
    
  • 信号(dispatch_semaphore_t):
    //通过信号实现同步功能
    - (void)semaphoreAction {
      NSLog(@"semaphore---begin");
      
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
      
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"semaphore --- %@",[NSThread currentThread]);
          
          dispatch_semaphore_signal(semaphore);
      });
      
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信号量=0则阻挡,>0则通过
      NSLog(@"semaphore---end");
    }
    
    输出:
    2018-03-20 18:14:28.265856+0800 GCD[56083:2576141] semaphore---begin
    2018-03-20 18:14:30.271145+0800 GCD[56083:2580996] semaphore --- <NSThread: 0x60c000078880>{number = 8, name = (null)}
    2018-03-20 18:14:30.271384+0800 GCD[56083:2576141] semaphore---end
    
    //通过信号实现锁
    - (void)semaphore1Action {
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
      dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
      
      for (int i = 0; i < 100; i++) {
          dispatch_async(queue, ^{
              // 相当于加锁
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              NSLog(@"i = %zd semaphore = %@", i, semaphore);
              // 相当于解锁
              dispatch_semaphore_signal(semaphore);
          });
      }
    }
    
    输出:
    2018-03-20 18:16:21.561341+0800 GCD[56217:2582806] i = 0 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.561717+0800 GCD[56217:2582805] i = 1 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.561999+0800 GCD[56217:2582803] i = 2 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.562277+0800 GCD[56217:2582804] i = 3 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.562508+0800 GCD[56217:2582812] i = 4 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.562745+0800 GCD[56217:2582823] i = 5 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.562979+0800 GCD[56217:2582824] i = 6 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.563213+0800 GCD[56217:2582825] i = 7 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.563442+0800 GCD[56217:2582826] i = 8 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    2018-03-20 18:16:21.563671+0800 GCD[56217:2582827] i = 9 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
    
  • 并发控制通过信号实现:
    void dispatch_async_limit(dispatch_queue_t queue,NSUInteger limitSemaphoreCount, dispatch_block_t block) {
      //控制并发数的信号量
      static dispatch_semaphore_t limitSemaphore;
      
      //专门控制并发等待的线程
      static dispatch_queue_t receiverQueue;
      
      //使用 dispatch_once而非 lazy 模式,防止可能的多线程抢占问题
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          limitSemaphore = dispatch_semaphore_create(limitSemaphoreCount);
          receiverQueue = dispatch_queue_create("receiver", DISPATCH_QUEUE_SERIAL);
      });
      
      // 如不加 receiverQueue 放在主线程会阻塞主线程
      dispatch_async(receiverQueue, ^{
          //可用信号量后才能继续,否则等待
          dispatch_semaphore_wait(limitSemaphore, DISPATCH_TIME_FOREVER);
          dispatch_async(queue, ^{
              !block ? : block();
              //在该工作线程执行完成后释放信号量
              long semaphore = dispatch_semaphore_signal(limitSemaphore);
              if (semaphore > 0) {
                  NSLog(@"\n");
              }
          });
      });
    }
    
    - (void)limitAction {
      for (int i = 0; i < 10; i++) {
          dispatch_async_limit([self serialQueue],3, ^{
              sleep(2);
              NSLog(@"------i = %d",i);
          });
      }
    }
    
    输出:
    2018-03-20 17:33:45.367914+0800 GCD[55534:2553299] ------i = 1
    2018-03-20 17:33:45.367914+0800 GCD[55534:2553303] ------i = 0
    2018-03-20 17:33:45.367916+0800 GCD[55534:2553300] ------i = 2
    2018-03-20 17:33:45.368276+0800 GCD[55534:2553303] 
    2018-03-20 17:33:47.373465+0800 GCD[55534:2553300] ------i = 3
    2018-03-20 17:33:47.373482+0800 GCD[55534:2553299] ------i = 4
    2018-03-20 17:33:47.373496+0800 GCD[55534:2553302] ------i = 5
    2018-03-20 17:33:47.373856+0800 GCD[55534:2553300] 
    2018-03-20 17:33:49.379032+0800 GCD[55534:2553302] ------i = 6
    2018-03-20 17:33:49.379048+0800 GCD[55534:2553299] ------i = 7
    2018-03-20 17:33:49.379048+0800 GCD[55534:2553303] ------i = 8
    2018-03-20 17:33:49.379452+0800 GCD[55534:2553299] 
    2018-03-20 17:33:51.383480+0800 GCD[55534:2553301] ------i = 9
    
  • 源码:

    代码在这里

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

推荐阅读更多精彩内容

  • 本文首发于我的个人博客:「程序员充电站」[https://itcharge.cn]文章链接:「传送门」[https...
    ITCharge阅读 347,573评论 308 1,926
  • 一、前言 上一篇文章iOS多线程浅汇-原理篇中整理了一些有关多线程的基本概念。本篇博文介绍的是iOS中常用的几个多...
    nuclear阅读 2,047评论 6 18
  • 1. GCD简介 什么是GCD呢?我们先来看看百度百科的解释简单了解下概念 引自百度百科:Grand Centra...
    千寻_544f阅读 362评论 0 0
  • 看到过不少文章描绘出同窗好友多年后重聚的场景,总是泪眼婆娑,感叹良多,心存戚戚,我以为这次见到Y后也会如此。 Y是...
    颂世梵歌阅读 434评论 0 2
  • 1.带实习生上课,声音太小,讲太多,学生不太买账。 接下来,还是自己来上课吧。进度不能落后。 2.实习生买了水果,...
    Alian__阅读 212评论 0 0