关于ios多线程问题

IOS多线程主要有三种

NSTheard
GCD
NSOperation & NSOperationQueue

NSTheard

这是最轻量级的多线程的方法,使用起来最直观的多线程编程方法。但是因为需要自己管理线程的生命周期,线程同步。经常使用NSThread进行调试,在实际项目中不推荐使用。

//取消线程
- (void)cancel;

//启动线程
- (void)start;

//判断某个线程的状态的属性
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;

//设置和获取线程名字
-(void)setName:(NSString *)n;
-(NSString *)name;

//获取当前线程信息
+ (NSThread *)currentThread;

//获取主线程信息
+ (NSThread *)mainThread;

//使当前线程暂停一段时间,或者暂停到某个时刻
+ (void)sleepForTimeInterval:(NSTimeInterval)time;
+ (void)sleepUntilDate:(NSDate *)date;
//获取当前线程
NSThread *current = [NSThread currentThread];
//获取主线程
NSThread *main = [NSThread mainThread];
NSLog(@"当前线程 --- %@",current);
NSLog(@"主线程 --- %@",main);

GCD

GCD是基于C语言底层API实现的一套多线程并发机制。简单来说CGD就是把 操作(任务) 放在 队列 中去执行。你只需定义好操作和队列就可以了。它是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。

操作分为同步和异步
同步操作:只会按顺序执行,执行顺序是确定的。
异步操作:在串行队列中执行顺序确定,在并行队列中执行顺序不确定
同步(sync) 和 异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕!
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程


队列:用于存放任务。一共有两种队列, 串行队列 和 并行队列。

这里写图片描述

//获取主队列,这是一个特殊的 串行队列。它用于刷新 UI,任何需要刷新 UI 的工作都要在主队列执行
dispatch_queue_t queue = ispatch_get_main_queue();
//创建串行队列
dispatch_queue_t q = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
//创建并行队列
dispatch_queue_t q = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

使用block来定义操作要执行的代码,q是已经定义好的,操作要加入的队列

//定义同步操作
dispatch_sync(q, ^{
 //要执行的代码 
});
//定义异步操作
dispatch_async(q, ^{
 //要执行的代码  
});

1.同步操作不管加入到何种队列,只会在主线程按顺序执行

dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 5; ++i) {
 dispatch_sync(q_serial, ^{
 NSLog(@"串行队列里的同步任务 %@ %d", [NSThread currentThread], i);
 });
}
for (int i = 0; i < 5; ++i) {
 dispatch_sync(q_concurrent, ^{
 NSLog(@"并行队列里的同步任务 %@ %d", [NSThread currentThread], i);
 });
}

2.异步操作只在非主线程的线程执行,在串行队列中异步操作会在新建的线程中按顺序执行。

dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
for(int i = 0; i < 5; ++i){
 dispatch_async(q_serial, ^{
  NSLog(@"串行队列 -- 异步任务 %@ %d", [NSThread currentThread], i);
 });
}

3.异步操作,并行队列
理论上并行队列会给每一个异步操作新建线程,然后让所有的任务并发执行。但是实际上系统能创建的线程数量是有限的,当创建的线程达到最大线程数以后,后面的异步操作就需要等待前面的操作执行完毕才能得到执行。哪个线程操作执行完毕,就把等待的异步任务安排到哪个线程

dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
for(int i = 0; i < 5; ++i){
 dispatch_async(q_concurrent, ^{
  NSLog(@"并行队列 -- 异步任务 %@ %d", [NSThread currentThread], i);
 });
}

NSOperation&NSOperationQueue

苹果公司把GCD中的操作抽象成NSOperation对象,把队列抽象成NSOperationQueue对象。
NSOperation 只是一个抽象类,所以不能封装任务。但它有 2 个子类用于封装任务。分别是:NSInvocationOperation 和 NSBlockOperation 。

扫描二维码关注公众号,回复: 1528422 查看本文章
//1.创建NSInvocationOperation对象
  NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

//2.开始执行
[operation start];

//3.创建NSBlockOperation对象
  NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"%@", [NSThread currentThread]);
  }];

//4.开始任务
[operation start];

NSBlockOperation 还有一个方法:addExecutionBlock: ,通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务 会并发执行,它会 在主线程和其它的多个线程 执行这些任务.

//1.创建NSBlockOperation对象
      NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
          NSLog(@"%@", [NSThread currentThread]);
      }];

      //添加多个Block
      for (NSInteger i = 0; i < 5; i++) {
          [operation addExecutionBlock:^{
              NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
          }];
      }

 //2.开始任务
 [operation start];

NOTE:addExecutionBlock 方法必须在 start() 方法之前执行,否则就会报错

设置依赖关系(执行顺序)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op1"];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op2"];
//op2在op1之后执行
[op2 addDependency:op1];//这里需要注意,一定要在addOperation之前设置依赖关系 
[queue addOperation:op1];
[queue addOperation:op2];

在NSOperation & NSOperationQueue中,我们不需要再像GCD那样定义操作的类型和队列的类型和控制操作的执行顺序了,你只需要直接设定操作的执行顺序就可以了。

Pthreads

仅供了解

POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。

猜你喜欢

转载自blog.csdn.net/storyteller321/article/details/75666255