谈谈iOS面试常提及到的线程间的通信

转载 2016年06月01日 09:27:29

程序猿思考问题时的样子

我们看图片只是乐呵一下,程序猿思考问题差不多就是这个样子,
今天同事在线程通信这一块有点疑问,我们下面来分析一下,系统都提供给我们那些,其实我们都知道,但是很少去关注这些API,也正是这些API,来回在APP中去执行各种不同的线程和队列


一、常见的线程间通信 GCD

我们先来看一个系统的例子:

    //开启一个全局队列的子线程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
            //1. 开始请求数据
            //...
            // 2. 数据请求完毕
            //我们知道UI的更新必须在主线程操作,所以我们要从子线程回调到主线程
        dispatch_async(dispatch_get_main_queue(), ^{

                //我已经回到主线程更新
        });

    });

如上所述,我们下面进行一个测试:

     //自定义队列,开启新的子线程
    dispatch_queue_t    custom_queue = dispatch_queue_create("concurrentqueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i=0; i<10; i++) {
        dispatch_async(custom_queue, ^{
            NSLog(@"## 并行队列 %d ##",i);
                //数据更新完毕回调主线程 线程之间的通信
            dispatch_async(dispatch_get_main_queue(), ^{

                NSLog(@"### 我在主线程 通信 ##");

            });


        });
    }
  • 线程中延迟调用某个方法
    //线程延迟调用 通信
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        NSLog(@"## 在主线程延迟5秒调用 ##");
    });
  • 线程休眠几秒的方法
    sleep(6); : 这里是休眠6秒

  • 常用的线程通信方法有以下几种:(GCD)

    1. 需要更新UI操作的时候使用下面这个GCD的block方法

      //回到主线程更新UI操作
      dispatch_async(dispatch_get_main_queue(), ^{
           //数据执行完毕回调到主线程操作UI更新数据
      });
    2. 有时候省去麻烦,我们使用系统的全局队列:一般用这个处理遍历大数据查询操作

      DISPATCH_QUEUE_PRIORITY_HIGH  全局队列高优先级
      DISPATCH_QUEUE_PRIORITY_LOW 全局队列低优先级
      DISPATCH_QUEUE_PRIORITY_BACKGROUND  全局队里后台执行队列
      // 全局并发队列执行处理大量逻辑时使用   
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      
      });
    3. 当在开发中遇到一些数据需要单线程访问的时候,我们可以采取同步线程的做法,来保证数据的正常执行

      //当我们需要执行一些数据安全操作写入的时候,需要同步操作,后面所有的任务要等待当前线程的执行
      dispatch_sync(dispatch_get_global_queue(0, 0), ^{
         //同步线程操作可以保证数据的安全完整性
      });

二、了解一下NSObject中的对象线程访问模式

  1. 我们介绍简单的perfermselecter选择器实现线程通信

         //数据请求完毕回调到主线程,更新UI资源信息  waitUntilDone    设置YES ,代表等待当前线程执行完毕
     [self performSelectorOnMainThread:@selector(dothing:) withObject:@[@"1"] waitUntilDone:YES];
  2. 如果需要执行到后台线程,则直接前往后台线程执行即可

     //将当前的逻辑转到后台线程去执行
    [self performSelectorInBackground:@selector(dothing:) withObject:@[@"2"]];
  3. 自己定义线程,将当前数据转移到指定的线程内去通信操作
     //支持自定义线程通信执行相应的操作
    NSThread * thread = [[NSThread alloc]init];
    [thread start];
        //当我们需要在特定的线程内去执行某一些数据的时候,我们需要指定某一个线程操作
    [self performSelector:@selector(dothing:) onThread:thread withObject:nil waitUntilDone:YES];
    //支持自定义线程通信执行相应的操作
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(testThread) object:nil];
    [thread start];
       //当我们需要在特定的线程内去执行某一些数据的时候,我们需要指定某一个线程操作
    [self performSelector:@selector(dothing:) onThread:thread withObject:nil waitUntilDone:YES];
  • 上面几种方法就是我们常用的对象调用常用的线程间通信,我们可以根据不同的情况,采取不同的线程执行状态.
增加一个特殊的线程常驻RunLoop 的做法
  • 需求: 我们经常要用到常驻线程来请求数据,但是请求有时候在线程会退出,这个时候我们需要用一下方法:
//有时候需要线程单独跑一个RunLoop 来保证我们的请求对象存在,不至于会被系统释放掉

    NSThread * runLoopThread = [[NSThread alloc]initWithTarget:self selector:@selector(entryThreadPoint) object:nil];
    [runLoopThread start];
    [self performSelector:@selector(handleMutiData) onThread:runLoopThread withObject:nil waitUntilDone:YES];

    //给线程增加一个run loop 来保持对象的引用
- (void)entryThreadPoint{

    @autoreleasepool {
        [NSThread currentThread].name = @"自定义线程名字";
        NSRunLoop * runloop = [NSRunLoop currentRunLoop];
        [runloop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
        [runloop run];


    }
}
- (void)handleMutiData{

    NSLog(@"## 我是跑在runloop的线程 ##");
}

最后测试截图如下,看下我们的线程是不是已经加入runloop 了


这个就是最后的执行了

本文暂时先介绍到这里,如果还想了解用信号量控制线程可以参考另外一篇博客:
iOS 关于dispatch_semaphore_t 和 dispatch_group_t 的简单实用,用于多网络异步回调通知



文/Raybon_lee(简书作者)
原文链接:http://www.jianshu.com/p/aacd3409f14b
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

相关文章推荐

iOS线程通信和进程通信的例子(NSMachPort和NSTask,NSPipe)

iOS线程间的通信iOS中,两个线程之间要想互相通信,可以使用:NSMachPort 下面是例子#define kMsg1 100 #define kMsg2 101- (void)viewDidL...
  • yxh265
  • yxh265
  • 2016年05月23日 18:33
  • 4996

iOS开发——多线程、NSThread、gcd、线程间通信

1.基础 1.1什么是进程 什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ、Xcode,系统就会分别启动...

iOS开发多线程-线程间的通信

一、简单说明   线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信     线程间通信的体现     1个线程传递数据给另1个线程     在1个线程中执行完特定任务后,...

多线程学习07-线程间通信

学习多线程07(之前跟着小码哥视频学习了多线程,准备把学到的东西放到网上,便于参考。仅有视频,所以所有文字都是自己打的,同时也温习一下多线程) 扩展: 原子和非原子属性 OC在定义属性时有non...

探究iOS开发中多线程之间的通信

在一个进程中,线程往往不是孤立存在的,一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和子线程间要进行通信。线程间通信的表现: 1个线程传递数据给...

iOS进阶面试题----多线程

1 多线程是什么  多线程是个复杂的概念,按字面意思是同步完成多项任务,提高了资源的使用效率,从硬件、操作系统、应用软件不同的角度去看,多线程被赋予不同的内涵,对于硬件,现在市面上多数的CPU都是多核...
  • xunyn
  • xunyn
  • 2013年11月08日 17:49
  • 55336

多线程学习10-GCD的线程间通信

学习多线程10(之前跟着小码哥视频学习了多线程,准备把学到的东西放到网上,便于参考。仅有视频,所以所有文字都是自己打的,同时也温习一下多线程) GCD的线程间通信,简单事例(下载图片)。 #i...

iOS缓存机制详解 LRU缓存机制

http://www.cnblogs.com/qiqibo/p/3520635.html 为什么要有缓存 应用需要离线工作的主要原因就是改善应用所表现出的性能。将应用内容缓存起来就...
  • jeffasd
  • jeffasd
  • 2016年05月27日 14:00
  • 765

GCD 和 NSOperation 区别及各自应用场景

GCD 相关介绍已经介绍过,点击查看,NSOperation相关介绍
  • Setoge
  • Setoge
  • 2016年08月06日 08:57
  • 1120

iOS开发多线程篇—线程间的通信

iOS开发多线程篇—线程间的通信   一、简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信   线程间通信的体现 1个线程传...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:谈谈iOS面试常提及到的线程间的通信
举报原因:
原因补充:

(最多只允许输入30个字)