多线程-GCD、NSOPeration

1、 多线程 --生命周期:新建、就绪、运行、组赛、死亡

//  在多线程中使用定时器必须开启Runloop.
[[NSRunLoop currentRunLoop] run];

1.NSThread
1> 开线程的几种方式

  • 先创建,后启动
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
  • 直接启动
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
[self performSelectorInBackground:@selector(run) withObject:nil];

2、其他用法

NSThread *current = [NSThread currentThread];
+ (NSThread *)mainThread; // 获得主线程

3 线程间通信
performSelectorOnMainThread.....

什么情况下选择GCD,和 NSOperationQueue呢? 依赖强选择后者。

-2.GCD(重点--把任务(线程)添加到队列里)
1> 队列的类型

//* 并发队列
获得全局的并发队列: dispatch_get_global_queue

//* 串行队列

a.自己创建
dispatch_queue_create
b.主队列
dispatch_get_main_queue

2> 执行任务的方法类型

* 同步(sync)执行
* 异步(async)执行

3> 了解队列和方法的配合使用

4> 线程间通信

dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 // 执行耗时的异步操作...(全局队列,由系统自动调用,在子线程中调用)

 dispatch_async(dispatch_get_main_queue(), ^{
   // 回到主线程,执行UI刷新操作
   });
});

5> 其他用法

dispatch_once
dispatch_after
dispatch_group_async\dispatch_group_notify

3.NSOperation
1> 基本使用

NSInvocationOperation
NSBlockOperation

// 2> NSOperationQueue(重点)

* 最大并发数设置
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

* 设置依赖(面试题)
[operationB addDependency:operationA]; // 操作B依赖于操作A

3> 如何解决一张图片(一个url)重复下载的问题?

答:利用Operation缓存操作,(key值 ,URL)根据图片的URL去images中取得图片,
判断是否存在,存在直接显示,否则,显示占位图片,然后根据图片的URL去查看operation中
是否存在下载操作,存在,则下载,否则创建下载操作,下载后放到images文件中保存

4、 自定义Operation(基本流程)

*  自定义方法的步骤:
*  1、重写main方法,自己创建自动释放池(因为异步操作,无法访问主线程的自动释放池)
*  2、在main方法中实现具体操作

// 重写- (void)main方法的注意点
自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

- (void)main
 {
  @autoreleasepool {
    //  正规写法,经常检查操作是否被取消,必须判断
    if (self.isCancelled) return;
       NSURL *downloadUrl = [NSURL URLWithString:self.url];
       NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时
        
      if (self.isCancelled) return;
        
      UIImage *image = [UIImage imageWithData:data];
        
      if (self.isCancelled) return;
      if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {         
         dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
                [self.delegate downloadOperation:self didFinishDownload:image];
            });
        }
    }

bolck 的使用?

  • 声明一个block
1> @property (nonatomic, copy) void (testBlock^)(); // 使用 copy
    
// 1.如果没有对block进行copy操作,block就存储于 [**栈空间**](指针)
// 2.如果对block进行copy操作,block就存储于 [**堆空间**](app管理)
    
// 3.如果block存储于栈空间,不会对block内部所用到的对象产生强引用
// 4.如果block存储于堆空间,就会对block内部所用到的对象产生强引用
Person *p = [[Person alloc]init];
__weak typeof(p) weakP = p;
    p.testBlock = ^ {
     [weakP run]; // 强引用
    };
2> block
(1)、block的内存管理
(2)、防止循环(retain)ARC :__weak , 非ARC __block

传送门:GCD 意外惊喜

你可能感兴趣的:(多线程-GCD、NSOPeration)