[多线程]NSThread, NSOperation 和 GCD

[多线程]NSThread, NSOperation 和 GCD


故事背景:忙碌了一周的程序员陈先生终于等来了周六早上,打算去喜茶看看,结果看到喜茶店只有一个窗口,后面排着一大条队伍(其实都是喜茶的托,你懂的),陈先生心里大骂:“MMP,原来是单线程,就不能拿雇托的钱多开几条线程吗?”

问题来了:什么是线程? 可以吃吗?


(一)基本概念

工欲善其事,必先利其器。所以弄清楚这些基本概念是学好多线程的基础。

进程: 指一个正在运行的应用程序。在故事中就好比喜茶店。
线程: 一个进程想要执行任务,就必须要有线程。一个进程中至少包含一条线程,该线程被称为主线程。例如喜茶的售货窗口就是一条线程。
多线程: 除主线程外开启一条或多条线程,同时(并行)执行不同的任务。这也是陈先生所希望的,多个窗口能提高销售效率。
多线程原理:CPU快速在各线程之间调度。
同步: 任务执行完成后再执行另一个,只在当前线程执行。例如背景故事中只允许一个窗口排队购买喜茶
异步: 任务每次允许完成多个。例如背景故事中陈先生希望的,多个窗口能同时排队购买。
队列: 队列是用来管理线程的,复制创建和回收线程,是先进先出(FIFO)结构的。分为串行队列并发队列
串行队列: 任务按照顺序被调度,前一个任务不执行完毕,队列不会调度。
并发队列: 只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不需要考虑前面是都有任务在执行,只要有线程可以利用,队列就会调度任务。

同步、异步、串行、并发 组合结果:

  • 串行队列+同步任务:不会开启新的线程,任务逐步完成。
  • 串行队列+异步任务:开启新的线程,任务逐步完成。
  • 并发队列+同步任务:不会开启新的线程,任务逐步完成。
  • 并发队列+异步任务:开启新的线程,任务同步完成。

(二)iOS中的多线程技术

iOS中有很多的多线程技术可供选择,到底选择哪一种后面会说的,这里只简单介绍几种多线程技术。

这里指介绍三种多线程技术:NSThread, NSOperation, GCD.

. NSThread

<1> 用法

  • 动态创建线程
- (void)createThreadByNSTread1
{
    NSThread * thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(method) object:nil];
}
  • 静态创建线程
- (void)createThreadByNSTread2
{
    [NSThread detachNewThreadSelector:@selector(runThread2) toTarget:self withObject:nil];
}

- (void)runThread2
{
    //由于静态方法没有返回值,如果需要获取新创建的thread,需要在selector中调用获取当前线程的方法
    NSThread *currentThread = [NSThread currentThread];
}
  • 线程开启

NSTread需要手动开启线程

[thread1 start];
  • 线程暂停/休眠
[NSThread sleepForTimeInterval:2.0/*休眠的时间*/];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
  • 线程取消
[thread1 cancel];
  • 线程停止
[thread1 exit];
  • 获取当前线程
[NSThread currentThread];
  • 获取主线程
[NSThread mainThread];
  • 设置优先级

iOS8以前使用

[NSThread setThreadPriority:1.0];

iOS8以后推荐使用

// NSQualityOfServiceUserInteractive:最高优先级,用于用户交互事件
// NSQualityOfServiceUserInitiated:次高优先级,用于用户需要马上执行的事件
// NSQualityOfServiceDefault:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级
// NSQualityOfServiceUtility:普通优先级,用于普通任务
// NSQualityOfServiceBackground:最低优先级,用于不重要的任务
[newThread setQualityOfService:NSQualityOfServiceUserInitiated];

<2> 线程间的通信

  • 在当前线程操作
[self performSelector:@selector(method)];
[self performSelector:@selector(method) withObject:nil];
[self performSelector:@selector(method) withObject:nil afterDelay:2.0];
  • 在主线程操作
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];

备注:一般用于更新UI

  • 指定某条线程上操作
[self performSelector:@selector(method) onThread:thread1 withObject:nil waitUntilDone:YES]; //这里指定为thread1线程
[self performSelectorInBackground:@selector(method) withObject:nil];//这里指定为后台线程

<3> 优缺点

  • 优点:
    简单,易操作,轻量级的iOS多线程工具。

  • 缺点:
    需要手动管理所有的线程活动,如生命周期、线程同步、睡眠等。

. NSOperation

<1> 用法简介

NSOperation需要和NSOperationQueue配合才能实现多线程编程。具体步骤如下:

  1. 先将需要执行的操作封装到一个NSOperation的子类对象中;(NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类)
  2. 然后将NSOperation对象添加到NSOperationQueue中;
  3. 系统会自动将NSOperationQueue中的NSOperation取出来;
  4. 将取出的NSOperation封装的操作放到一条新线程中执行。

<2> NSOperation的子类

NSOperation是一个抽象类,不具有封装任务的能力,必须使用它的子类来封装任务。它的子类如下:

  1. NSInvocationOperation:具体项目中较少用;
  2. NSBlockOperation:相对较常使用该子类;
  3. 自定义子类继承NSOperation:很少使用。

详细运用如下:

  • NSInvocationOperation

(未完待续)

你可能感兴趣的:(Objective-c)