首页 > 代码库 > iOS多线程技术

iOS多线程技术

说明:开发技术大同小异,帖子写出来不是为了晒的,只是一个学习记录过程,有错误欢迎指正,喜欢喷人的请滚蛋。

一、实现方案

在iOS中有三种多线程实现技术,它们分别是NSThread、GCD 、NSOperation。

  NSThread:基于OC编写,更加面向对象,可直接操作线程对象,需要程序员手动管理线程生命周期,开发中偶尔使用。

  GCD:基于c语言编写,旨在替代NSThread线程技术,能充分利用设备的多核,系统自动管理线程生命周期,开发中经常使用。

  NSOperation:底层基于GCD封装的一套OC实现,更加面向对象,系统自动管理线程生命周期,开发中经常使用。

1.NSThread

一个NSthread对象就代表一条线程

相关设置

 

设置线程的名字

 

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

 

- (NSString *)name;

 

获得当前线程

 

[NSThread currentThread];

 

线程调度优先级:优先级范围在0.0~1.0之间,默认是0.5,值越大,优先级越高,越容易被调度。

 

- (void)setThreadPriority:(double)priority

 

- (double)threadPriority

 

主线程

 

+ (NSThread *)mainThread; // 获得主线程

 

- (BOOL)isMainThread; // 是否为主线程

 

+ (BOOL)isMainThread; // 是否为主线程

 

1.线程的创建

 1>NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(callback) object:nil];

 [thread start];

2>[NSThread detachNewThreadSelector:@selector(callback:) toTarget:self withObject:nil];

3>[self performSelectorInBackground:@selector(callback:) withObject:nil];

第一种相比较后两种而言可以更加精准的控制线程相关设置,比如线程名称,优先级等。

2.线程的状态

新建:线程创建出来

就绪:调用线程start方法,加载到线程池等待调度

运行:线程得到cpu调度

阻塞:线程睡眠或等待同步锁

死亡:线程执行完毕或者强制退出或者程序崩溃

3.线程的同步

当多个线程访问共享资源时,会有数据安全问题,例如写出错,读取脏数据,解决办法是加互斥锁。

//加锁

 @synchronized(self){

  访问共享资源代码

}//解锁

4.线程的通信

有时候多个线程之间需要相互通信,互相传递数据,比如在子线程下载好图片资源后需要回到主线程更新UI界面

可以在子线程内部发发异步请求向主线程传递数据。

- (void)threadCommunicate

{

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];

    [thread setThreadPriority:1];

    thread.name = @"线程A";

    [thread start];

}

- (void)download

{

    //1.下载图片

    NSData *data = http://www.mamicode.com/[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"]];

    UIImage *image = [UIImage imageWithData:data];

    //2.更新图片(子线程下载的图片返回给主线程更新UI界面)

    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

}

2.GCD(Grand Central Dispatch)

GCD会充分利用设备的多核技术,自动管理线程的生命周期,程序员只需要将任务放在相关队列中就可以了,不用关心线程的状态

首先理解两个概念

队列:

串行队列:队列的任务串行执行

并发队列:队列的任务并发执行

请求:

同步:不会开启新线程

异步:会开启新线程,只有放在并发队列中才会实现多线程技术,放在串行队列中只会开启一个线程且任务串行执行。

- (void)viewDidLoad{    [super viewDidLoad];    //1.串行队列(队列里面的操作串行执行)    self.serialQueue = dispatch_queue_create("串行对列",DISPATCH_QUEUE_SERIAL);    //2.并发队列(队列里面的操作并发执行)    self.concurrentQueue = dispatch_queue_create("并行队列",DISPATCH_QUEUE_CONCURRENT);    //3.全局队列(系统自带并发队列)    self.globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    //4.主队列(与主线程相关)    self.mainQueue = dispatch_get_main_queue();    NSLog(@"主线程%@",[NSThread currentThread]);    //[self gcdCommunicate];}/** * 同步函数dispatch_sync不会开启新线程 */- (void)sync{    //在串行队列中同步执行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.serialQueue, ^{            NSLog(@"同步串行%@--%d",[NSThread currentThread],i);        });    }    //在并发队列中同步执行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.concurrentQueue, ^{            NSLog(@"同步并发%@",[NSThread currentThread]);        });    }    //在全局队列中同步执行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.globalQueue, ^{            NSLog(@"同步全局%@",[NSThread currentThread]);        });    }    //在主队列中同步执行操作#warning 在主线程中执行同步操作会卡住    dispatch_sync(self.mainQueue, ^{        NSLog(@"同步主%@",[NSThread currentThread]);    });}/** * 异步函数dispatch_async会开启新线程 */- (void)async{    //在串行队列中异步执行操作(开启一条子线程,操作串行执行)    for(int i = 0;i<10;i++){        dispatch_async(self.serialQueue, ^{            NSLog(@"异步串行%@---%d",[NSThread currentThread],i);        });    }    //在并发队列中异步执行操作(开启多条子线程,操作并发执行)    for(int i = 0;i<10;i++){        dispatch_async(self.concurrentQueue, ^{            NSLog(@"异步并发%@---%d",[NSThread currentThread],i);        });    }    //在全局队列中异步执行操作(开启多条子线程,操作并发执行)    for(int i = 0;i<10;i++){        dispatch_async(self.globalQueue, ^{            NSLog(@"异步全局%@---%d",[NSThread currentThread],i);        });    }    //在主队列中异步执行操作(在主线程上执行,操作串行执行)    for(int i = 0;i<10;i++){        dispatch_async(self.globalQueue, ^{            NSLog(@"异步主%@---%d",[NSThread currentThread],i);        });    }}/** * GCD的线程通信 */- (void)gcdCommunicate{    dispatch_async(self.globalQueue, ^{        NSLog(@"当前线程%@", [NSThread currentThread]);        // 下载图片        NSURL *url = [NSURL URLWithString:@"http://news.baidu.com/z/resource/r/image/2014-06-22/2a1009253cf9fc7c97893a4f0fe3a7b1.jpg"];        NSData *data = http://www.mamicode.com/[NSData dataWithContentsOfURL:url]; "color: #000000;"> [UIImage imageWithData:data];                // 回到主线程显示图片        dispatch_async(self.mainQueue, ^{            NSLog(@"当前线程%@", [NSThread currentThread]);            self.imageView.image = image;        });    });}

3.NSOperation

NSOperation底层基于GCD,使用OC编写,更加面向对象,是苹果官方比较推荐的技术

配合使用NSOperation和NSOperationQueue也能实现多线程编程

1>使用步骤

 首先创建NSOperation对象,将操作封装到里面

然后将NSOperation对象添加到NSOperationQueue中

系统会自动将NSOperation中封装的操作放到一条新线程中执行

2>子类

NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类

使用NSOperation子类的方式有3种

NSInvocationOperation

NSBlockOperation

自定义子类继承NSOperation,实现内部相应的方法

/** * NSInvocationOperation的使用 */- (void)invocationOperation{    // 1.创建操作对象, 封装要执行的操作    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(callback) object:nil];    // 2.启动操作(默认情况下,如果操作没有放到队列queue中,都是同步执行)    [operation start];}- (void)callback{    NSLog(@"当前线程%@",[NSThread currentThread]);}/** * NSBlockOperation的使用 */- (void)blockOperation{    // 1.创建操作对象, 封装要执行的操作    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"当前线程%@--操作1",[NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"当前线程%@--操作2",[NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"当前线程%@--操作3",[NSThread currentThread]);    }];    //监听操作    operation.completionBlock = ^(){        NSLog(@"当前线程%@--操作完毕", [NSThread currentThread]);    };    // 2.启动操作(如果只有一个操作不会开启线程,如果有多个操作,就会开启新线程)    [operation start];}/** * NSOperationQueue的使用 */- (void)OperationQueue{    //1.创建操作队列    NSOperationQueue *queue = [[NSOperationQueue alloc] init];    //设置队列的最大并发数    queue.maxConcurrentOperationCount = 3;    //2.创建操作    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"当前线程%@-操作1",[NSThread currentThread]);    }];    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"当前线程%@-操作2",[NSThread currentThread]);    }];    NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocation) object:nil];        //设置依赖    //[operation2 addDependency:operation1];    //[operation3 addDependency:operation2];            //3.操作放在队列中    [queue addOperation:operation1];    [queue addOperation:operation2];    [queue addOperation:operation3];}- (void)invocation{    NSLog(@"当前线程%@-操作3",[NSThread currentThread]);}

//写的有点晚了,本来想写细点,不过感觉这些代码和思想都很简单,方便以后自己重温就行了,所以写的糙了点,海涵。

 

iOS多线程技术