iOS - FuThD/FuThD.github.io GitHub Wiki

###pthread线程

####pthread简介

  • POSIX线程(POSIX threads), 简称Pthreads, 是线程的POSIX标准。
  • 该标准定义了创建和操纵线程的一整套API。
  • 在类Unix操作系统(Unix、Linux、Mac OS X等)中, 都使用Pthreads作为操作系统的线程。
  • 简单地说,这是一套在很多操作系统上都通用的多线程API, 所以移植性很强, 当然在 iOS 中也是可以的。不过这是基于 c语言 的框架,使用起来难度极大!

####代码演示

1. C语言中的 void * 等同于  OC 中的 id
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //创建子线程
    pthread_t pthread;
    /**
     
     1. 返回值: 返回0表示成功, 非0表示失败
     2. 参数:
        第一个参数 线程编号的地址
        第二个参数 线程的属性
        第三个参数 线程要执行的函数void *    (*)    (void *)
        void * 指向任何类型的指针  有点类似OC中的id
        第四个参数 要执行的函数的参数
     */
    int result =  pthread_create(&pthread, NULL, demo, NULL);
    
    NSLog(@"touchesBegan  %@",[NSThread currentThread]);
    
    if (result == 0) {
        NSLog(@"成功");
    }else {
        NSLog(@"失败");
    }
}

void *demo(void *param) {
    NSLog(@"hello %@",[NSThread currentThread]);
    return NULL;
}

###NSThread线程

####NSThread简介

  • 苹果封装, OC完全面向对象
  • 可以直接操作线程对象, 直观且方便
  • 声明周期需要程序员手动管理
  • 偶尔使用, 比如: [NSThread currentThread]; 获取当前线程

####代码演示

1. // alloc init 实例化方法
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argumen;

1> 作用: 实例化一个线程对象, 执行 selector 方法
   * "注意: 要启动线程, 需要调用 start 方法"
2> 参数
   * 提供 selector 方法的对象, 通常是 self  (selector方法的拥有者)
   * selector 方法
   * 传递给 selector 方法的参数
3> start 方法
   * 将线程对象放入可调度线程池等待CPU调度
   cancel 方法
   * 通知线程取消
------------------------------------
2. // 类方法
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

1> 作用: 创建并自动启动线程, 执行 selector 方法
2> 参数:
    * 提供 selector 方法的对象, 通常是 self  (selector方法的拥有者)
    * selector 方法
    * 传递给 selector 方法的参数
------------------------------------
3. // NSObject 分类方法
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg

1> 作用: 隐式(没有任何跟线程相关的字眼)创建并启动线程,执行 selector 方法
2> 参数:
    * selector 方法
    * 传递给 selector 方法的参数
3> 注意: "既然是 NSObject 的分类方法, 任何继承自 NSObject 的对象都可以直接调用这个方法,因此 perform 方法使用最灵活"

总结:
    ** 使用 detach 和 perform 两种方法创建线程更加简便
    ** 缺点:无法对线程进行更详细的设置

###GCD

####GCD简介

  • Grand Central Dispatch, 听名字就霸气
  • 为多核的并行运算提出的解决方案, 会自动合理地利用更多的CPU内核(比如双核、四核)
  • 自动管理线程的声明周期(创建线程、调度任务、销毁线程)
  • 引入了 block, 使用起来简单灵活, 经常使用

####代码演示

//串行队列  同步执行
-(void) demo1 {
    
    //创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("qh", DISPATCH_QUEUE_SERIAL);
    
    dispatch_sync(queue, ^{
        
        for (int i = 0 ; i < 10 ; i ++ ) {
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
        }
        
    });
    
}

//串行队列 异步执行
-(void) demo2{
    
    //创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("qh", DISPATCH_QUEUE_SERIAL);
    for (int i = 0 ; i < 10 ; i ++ ) {
    dispatch_async(queue, ^{
        
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
       
    });
}
}

//并行队列 同步执行
-(void) demo3{
    for (int i = 0 ; i < 10 ; i ++ ) {
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
        
    });
  }
}

//并行队列 异步执行
-(void) demo4{
    
    dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0 ; i < 10 ; i ++ ) {
    dispatch_async(queue, ^{
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
        
    });
}
    
}

//主线程 同步队列 死锁
-(void) demo5{
    for (int i = 0 ; i < 10 ; i ++ ) {
        dispatch_sync(dispatch_get_main_queue(), ^{
            
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
            
        });
    }
}

//主线程 异步队列
-(void) demo6{
    for (int i = 0 ; i < 10 ; i ++ ) {
        dispatch_async(dispatch_get_main_queue(), ^{
            
            NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
            
        });
    }
}

###NSOperation

####NSOperation简介

  • 苹果公司在 iOS 4.0 对 GCD 进行的封装
  • 完全面向对象, 使用起来更好理解
  • 苹果极力推荐使用, 经常使用

####代码演示 建NSInvocationOperation对象

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
调用start方法开始执行操作
- (void)start;

创建NSBlockOperation对象

+ (id)blockOperationWithBlock:(void (^)(void))block;

通过addExecutionBlock:方法添加更多的操作

- (void)addExecutionBlock:(void (^)(void))block;

添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;

一旦执行操作,就会调用target的sel方法

主队列 添加到主队列的操作,最终都执行在主线程上

[NSOperationQueue mainQueue]

当前队列 获取当前操作所在的队列

[NSOperationQueue currentQueue]

最大并发数的相关方法

- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

取消队列的所有操作

- (void)cancelAllOperations;

提示:也可以调用NSOperation的- (void)cancel方法取消单个操作 暂停和恢复队列

- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended;

设置NSOperation在queue中的优先级,可以改变操作的执行优先级

- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;

可以监听一个操作的执行完毕

- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;

NSOperation之间可以设置依赖来保证执行顺序 比如一定要让操作A执行完后,才能执行操作B,可以这么写

[operationB addDependency:operationA]; // 操作B依赖于操作A

###GCD 和 NSOperation的区别 ####GCD GCD中两个核心的概念。队列和任务,GCD中是怎么实现的。首先是创建队列,然后定制任务。最后是将任务添加至队列。 然后这个里面就有很多概念了。队列中有串行队列,并行队列,主队列,全局队列。其中要求重点掌握的就是主队列和全局队列,其实主队列本质上就是一个串行队列,全局队列就是一个并行队列。 任务的话,有同步任务和异步任务。 任务之间的依赖可以使用同步任务的方式和barrier(阻塞)来执行。 最后是线程间通讯,不管同步还是异步是不是最后都要回到主队列中去更新数据或者刷新UI显示。是不是dispatch_sync(dispatch_get_main_queue). 然后GCD中还有一些小的知识点就是 主队列,同步执行会出现死锁! GCD中一次性执行代码!有一个非常重要的应用场景就是单例! 另外一个知识点就是延迟操作。Dispatch_after ####NSOperation 将操作(异步)添加到队列(全局的并发队列)。 NSOperation的使用是不是更加面象对象。NSOperation是一个抽象的类,使用的是他的子类。 取消和暂停都会把正在执行的任务先执行完毕后,才会取消或者暂停队列中的任务。 然后还有一个最大并发数,GCD中我们能控制线程数吗?不能,GCD中会自动帮我们管理线程。需要注意的就是最大并发数并不是线程数,我们可以通过最大并发数来控制线程数。 NSoperation中也可以实现操作依赖,GCD中实现操作依赖的方式有什么? 同步和阻塞 这个和GCD中有不同的就是NSOperation可以跨队列设置操作间的依赖。

⚠️ **GitHub.com Fallback** ⚠️