在项目开发中,一个进程默认情况下,只有一个线程,也就是我们说的主线程。如果我们把所有的操作都在主线程中进行的话,很有可能会造成主线程堵塞,界面很卡,给用户很不好的体验效果。比较我们进入一个界面需要网络请求时,假如这个请求要十秒钟才能请求下来,如果这些都在主线程中进行的话,那这10秒钟我们就只能干看着手机,就连返回都不能,很显然,这样的应用时太坑爹了的。所以就需要我们手动来创建一个或者多个线程,来分担主线程的繁重的任务。

iOS现在创建线程,多线程操作的方式一共有三种:NSThread、NSOperation、GCD。废话不多说,进入正题。下面就是这三种线程一些简单的介绍。

一 NSThread方式创建线程

两种方式创建:

1.[NSThreaddetachNewThreadSelector:@selector(doSomething2:) toTarget:self withObject:@”传的参数”];
2.NSThread *myThread =[[NSThread alloc] initWithTarget:self selector:@selector(doSomething2:)object:@”参数”];
[myThread start];
//只有start的之后,线程才会正式启动。

NSThread方式进行多线程操作时,多个线程时必须上锁NSLock,在一个线程完成操作后解锁[theLock unlock];

通过NSCondition的signal方法,发送信号的方式,在这个线程中唤醒另外一个线程的等待


二 NSOperationQueue和NSOperation

通过NSOperationQueue建立一个线程管理器,建立过程:

建立NSOperationQueue对象→建立NSOperation对象→将NSOperation对象加入到队列中→release掉NSOperation对象(非ARC下)

NSOperation对象通过NSInvocationOperation类建立,是NSOperation的子类
 NSOperationQueue通过setMaxConcurrentOperationCount方法设定队列中线程的个数

 

创建方法:

NSOperationQueue *queue= [NSOperationQueue new];
NSInvocationOperation*operation = [[NSInvocationOperation alloc] initWithTarget:selfselector:@selector(doSomething:) object:@”传的参数是个字符串”];
[queueaddOperation:operation];
 
//运行在另外一个线程
-  (void)doSomething:(NSString *)string{
NSLog(@”%@”,string);
}

三 GCD

GCD:Grand Central Dispatch  是Apple开发的一个多核编程的解决方法。和block一起使用,使用最方便。

#pragma mark -  系统方法的GCD
/*
 dispatch_async开启一个异步请求
 第一个参数是指定一个gcd队列,第二个参数是分配一个处理事物的程序块到该队列
 dispatch_get_global_queue指定为全局队列
 第一个参数是分配事物处理程序的块队列优先级。
 #define DISPATCH_QUEUE_PRIORITY_HIGH     2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT  0
 #define DISPATCH_QUEUE_PRIORITY_LOW     (-2)

- (void)GCDwaysOne{
//后台执行
dispatch_async(dispatch_get_global_queue(0,0), ^{
 //something
});
    
//主线程执行
dispatch_async(dispatch_get_main_queue(), ^{
//something
});
    
//一次性执行
staticdispatch_once_t
dispatch_once(&onceToken, ^{
//something
});
    
//延迟1秒执行
double delayOne =1.0;
dispatch_time_t time =dispatch_time(DISPATCH_TIME_NOW, delayOne *NSEC_PER_SEC);
dispatch_after(time,dispatch_get_main_queue(), ^{

});
}

#pragma mark -  自定义dispatch_queue_t
- (void)GCDwaysTwo{
 //自定义的dispatch_queue_t
 dispatch_queue_t url_queue =dispatch_queue_create("something",NULL);
 dispatch_async(url_queue, ^{
//something

//非arc下需要释放
//dispatch_release(url_queue);
}

#pragma mark -  后台多线程并发
/*

异步和并发的不同点:

异步只是提供了一种多线程处理的概念,

并发是更像是异步的一种大规模实现

*/
- (void)GCDwaysThree{
dispatch_group_t group =dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(0,0), ^{
//并行执行的线程一
});
    
dispatch_group_async(group,dispatch_get_global_queue(0,0), ^{
//并行执行的线程二
});
    
dispatch_group_notify(group,dispatch_get_global_queue(0,0), ^{
//汇总结果
});
}



这里我对三种方式创建多线程也做了一下总结,关于他们各自的优缺点。

优点:

NSThread:相比其它两种方式更加轻量,使用简单。

NSOperation:不需要关心线程管理,数据同步的事情;

NSOperationQueue可以添加依赖,让一个线程在另一个完成后才执行,没有上锁解锁这些繁琐的操作;

(NSOperation是基于OC实现的,所以是面向对象的创建线程的技术,网络请求的时候第三方框架,AFNetworking就是直接用的NSOperation)

GCD:抽象度是最高的,使用也就越简单,是Apple最推荐使用,基于C语言的框架开发的。而且GCD使用时,会与block结合起来用,比较简便高效。并且GCD能够在“多核”上使用多线程。


缺点:

NSThread:需要自己管理线程的生命周期,线程同步。线程同步对数据枷锁会有一定的系统开销。

注:所有创建的子线程都不能对UI进行操作,需回到主线程。例:网络请求完成后需要刷新界面就必须回到主线程。