iOS 多线程

一 多线程基础面试

 1.进程:进程就是系统中正在运行的应用程序.每一个进程是相互独立的且都运行在各自受保护的运行空间内.  编程

  好比同时打开迅雷、Xcode,系统就会分别启动2个进程.缓存

  2.线程:进程在执行任务是必须开辟线程,进程中的全部任务都在线程中进行.一个进程能够开辟一条线程,也能够开辟多条线程.安全

  好比酷狗音乐这个进程在执行播放音乐这个线程的同时,还在执行下载音乐这条线线程.多线程

二 线程的串行并发

  在同一时间一个线程只能执行一个任务,若是一个线程有多条任务要执行就得按前后顺序执行,一个线程不能同时进行多个任务.app

三 多线程框架

  一个进程能够开辟多条线程,每条线程能够执行不一样的任务,看上去是每条相称在同时进行,实际上是CPU在不一样线程间快速的切换.异步

  CPU在同一时间只能执行一条线程.async

  多线程技术能够提升执行程序的效率,提升资源利用率.

  可是在建立线程耗内存耗时间,且若是线程开辟太多也会下降程序的性能,并且多线程的程序设计难度也更大.

四 多线程在IOS开发中的应用

  一个iOS程序运行后,会自动开辟主线程(又叫UI线程).

  主线程主要用来显示和刷新UI界面以及处理UI事件.

  主线程使用过程当中的注意事项:主线程处理耗时操做时会有卡死的感受,影响UI的流畅度,所以不可将耗时较多的操做放在主线程中.

  主线程只用来显示和刷新UI界面以及处理UI事件.

五 多线程的实现方案

  1.pthread 几乎不用

  2.NSThread 几乎不用

  3.GCD 常使用

    GCD基于C语言,自动管理现成的生命周期,可从分利用多喝处理器来处理线程. 

  4.NSOperation 常使用

    NSOperation基于GCD自动管理线程的生命周期.

六 NSThread(掌握)

  1.建立和启动线程的3种方式

  

/**1  先建立,后启动*/
  // 建立
  NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:nil];
  // 启动
  [thread start];

/**2  建立完自动启动*/
  [NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:nil];

/**3  隐式建立(自动启动)*/
  [self performSelectorInBackground:@selector(download:) withObject:nil];

 

 

  2.常见方法

  1> 得到当前线程

+ (NSThread *)currentThread; 

  2> 得到主线程

+ (NSThread *)mainThread; 

  3> 睡眠(暂停)线程 

+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

  4> 设置线程的名字

- (void)setName:(NSString *)n;
- (NSString *)name;

 

七 线程同步(掌握)

  1.实质:为了防止多个线程抢夺同一个资源形成的数据安全问题

  2.实现:给代码加一个互斥锁(同步锁)

@synchronized(self) {
    // 被锁住的代码
  }

八 GCD

  1.队列和任务

  1> 任务 :须要执行什么操做

  * 用block来封装任务

   2> 队列 :存听任务

  * 全局的并发队列 : 可让任务并发执行

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  * 本身建立的串行队列 : 让任务一个接着一个执行

dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL); 

  * 主队列 : 让任务在主线程执行  

dispatch_queue_t queue = dispatch_get_main_queue();

 

  2.执行任务的函数

  1> 同步执行 : 不具有开启新线程的能力

  dispatch_sync...

 

  2> 异步执行 : 具有开启新线程的能力

  dispatch_async...

 

  3.常见的组合(掌握)

  1> dispatch_async + 全局并发队列

  2> dispatch_async + 本身建立的串行队列

 

  4.线程间的通讯(掌握)

dispatch_async(dispatch_get_main_queue(), ^{

       // 回到主线程,执行UI刷新操做
     });
});

 

 

  5.GCD的全部API都在libdispatch.dylib,Xcode会自动导入这个库

  * 主头文件 : #import <dispatch/dispatch.h>

 

  6.延迟执行(掌握)

  1> perform....

// 3秒后自动回到当前线程调用self的download:方法,而且传递参数:@"http://555.jpg"
[self performSelector:@selector(download:) withObject:@"http://555.jpg" afterDelay:3];

  2> dispatch_after...

// 任务放到哪一个队列中执行

  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

  double delay = 3; // 延迟多少秒

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{

      // 3秒后须要执行的任务  

  });

 

  7.一次性代码(掌握) 

static dispatch_once_t onceToken;

  dispatch_once(&onceToken, ^{

      // 这里面的代码,在程序运行过程当中,永远只会执行1次

  });

 

 九 单例模式(懒汉式)

  1.ARC

  

@interface HMDataTool : NSObject
  
+ (instancetype)sharedDataTool;  
@end

@implementation HMDataTool   // 用来保存惟一的单例对象   static id _instace;   + (id)allocWithZone:(struct _NSZone *)zone   {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{    _instace = [super allocWithZone:zone];    });    return _instace;   }   + (instancetype)sharedDataTool   {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{    _instace = [[self alloc] init];   });   return _instace;   }   - (id)copyWithZone:(NSZone *)zone   {    return _instace;   }   @end

 

 2 非ARC

 2.非ARC
  @interface HMDataTool : NSObject
  + (instancetype)sharedDataTool;
  @end
 

  @implementation HMDataTool

  // 用来保存惟一的单例对象
  static id _instace;

  + (id)allocWithZone:(struct _NSZone *)zone
  {      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          _instace = [super allocWithZone:zone];
      });
      return _instace;
  }

  + (instancetype)sharedDataTool
  {
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{

          _instace = [[self alloc] init];

      });
      return _instace;
  }

  - (id)copyWithZone:(NSZone *)zone
  {
      return _instace;
  }

  - (oneway void)release {

  }

  - (id)retain {
      return self;
  }

  - (NSUInteger)retainCount {
      return 1;
  }

  - (id)autorelease {
      return self;
  }
 @end

 

 

十 NSOperation和NSOperationQueue

  1.队列的类型

  1> 主队列

  * [NSOperationQueue mainQueue]

  * 添加到"主队列"中的操做,都会放到主线程中执行

 

  2> 非主队列

  * [[NSOperationQueue alloc] init]

  * 添加到"非主队列"中的操做,都会放到子线程中执行

 

  2.队列添加任务

  * - (void)addOperation:(NSOperation *)op;

  * - (void)addOperationWithBlock:(void (^)(void))block;

 

  3.常见用法

  1> 设置最大并发数

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

  2> 队列的其余操做

  * 取消全部的操做

- (void)cancelAllOperations;

  * 暂停全部的操做

[queue setSuspended:YES];

  * 恢复全部的操做  

[queue setSuspended:NO];

 

  4.操做之间的依赖(面试题)

  * NSOperation之间能够设置依赖来保证执行顺序

  * [operationB addDependency:operationA];

  // 操做B依赖于操做A,等操做A执行完毕后,才会执行操做B

  * 注意:不能相互依赖,好比A依赖B,B依赖A

  * 能够在不一样queue的NSOperation之间建立依赖关系

 

  5.线程之间的通讯

  

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

  [queue addOperationWithBlock:^{

      // 1.执行一些比较耗时的操做

    
      // 2.回到主线程

      [[NSOperationQueue mainQueue] addOperationWithBlock:^{  

        
      }];

  }];

 

 

十一 从其余线程回到主线程的方式

  

//perform...

  [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

 
//GCD

  dispatch_async(dispatch_get_main_queue(), ^{

  });

 
//NSOperationQueue

  [[NSOperationQueue mainQueue] addOperationWithBlock:^{

    

  }];

 

 

十二 判断编译器的环境:ARC仍是MRC?

  #if __has_feature(objc_arc)

  // 当前的编译器环境是ARC

 

  #else

  // 当前的编译器环境是MRC

 

  #endif

 

十三 类的初始化方法

  1.+(void)load

  * 当某个类第一次装载到OC运行时系统(内存)时,就会调用

  * 程序一启动就会调用

  * 程序运行过程当中,只会调用1次

 

  2.+(void)initialize

  * 当某个类第一次被使用时(好比调用了类的某个方法),就会调用

  * 并不是程序一启动就会调用

 

  3.在程序运行过程当中:1个类中的某个操做,只想执行1次,那么这个操做放到+(void)load方法中最合适

 

十四 第三方框架的使用建议

  1.用第三方框架的目的

  1> 开发效率:快速开发,人家封装好的一行代码顶本身写的N行

  2> 为了使用这个功能最牛逼的实现

 

  2.第三方框架过多,不少坏处(忽略不计)

  1> 管理、升级、更新

  2> 第三方框架有BUG,等待做者解决

  3> 第三方框架的做者不幸去世、中止更新(潜在的BUG无人解决)

  4> 感受:本身好水

 

  3.好比

  流媒体:播放在线视频、音频(边下载边播放)

  很是了解音频、视频文件的格式

  每一种视频都有本身的解码方式(C\C++)

 

  4.总结

  1> 站在巨人的肩膀上编程

  2> 没有关系,使劲用那么比较稳定的第三方框架

 

十五 cell的图片下载

  1.面试题

  1> 如何防止一个url对应的图片重复下载

  * “cell下载图片思路 – 有沙盒缓存”

 

  2> SDWebImage的默认缓存时长是多少?

  * 1个星期

 

  2.SDWebImage

  1> 经常使用方法

  

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options   progress:  (SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

 

 

  2> 内存处理:当app接收到内存警告时

  

/**
当app接收到内存警告
*/

  - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application

  {
    SDWebImageManager *mgr = [SDWebImageManager sharedManager];

      // 1.取消正在下载的操做

      [mgr cancelAll];

      // 2.清除内存缓存

      [mgr.imageCache clearMemory];

  }

 

  3> SDWebImageOptions

  * SDWebImageRetryFailed : 下载失败后,会自动从新下载

  * SDWebImageLowPriority : 当正在进行UI交互时,自动暂停内部的一些下载操做

  * SDWebImageRetryFailed | SDWebImageLowPriority : 拥有上面2个功能

相关文章
相关标签/搜索