1、NSThread类: 线程类,一个线程对象就是一个线程
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
方法一:
// 创建一个线程对象
NSThread *thread = [[NSThread alloc] initWithTarget:selfselector:@selector(snippet) object:nil];
thread.name=@"sum";
开始线程
[thread start];
线程释放
[thread release];
方法二:
[NSThreaddetachNewThreadSelector:@selector(snippet)toTarget:selfwithObject:nil];
2、Cocoa NSOperation:一个NSOperationQueue是一个线程
要实现多线程,首先创建NSOperation对象,然后将NSOperation对象放入NSOperationQueue队列中。
优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。
创建NSOperation对象,因为其是抽象类,不能直接创建对象,使用系统的两个子类可以实现:NSInvocationOperation 和 NSBlockOperation。
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。
子类1:NSInvocationOperation
NSInvocationOperation*operation1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(snippet)object:nil];
NSInvocationOperation*operation2 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(snippet)object:nil];
子类2:NSBlockOperation
NSBlockOperation*blockOperation1 = [NSBlockOperationblockOperationWithBlock:^{
[selfsnippet];
}];
NSBlockOperation*blockOperation2 = [NSBlockOperationblockOperationWithBlock:^{
[selfsnippet];
}];
创建NSOperationQueue对象
NSOperationQueue*queue = [[NSOperationQueuealloc]init];
指定最多线程数
queue.maxConcurrentOperationCount=1;
注意:设为1就表示queue每次只能执行一个操作。不过operation执行的顺序仍然依赖于其它因素,比如operation是否准备好和operation的优先级等。
设置operation1依赖于operation2(operation2执行完之后再执行operation1)
[operation1 addDependency:operation2];
queue中添加operation对象
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:blockOperation1];
[queue addOperation:blockOperation2];
一旦添加到operation queue,queue就拥有了这个Operation对象并且不能被删除,唯一能做的事情是取消
取消单个操作
[operation1 cancel];
取消queue中所有的操作
[queue cancelAllOperations];
暂停queue
[queue setSuspended:YES];
注意:暂停一个queue不会导致正在执行的operation在任务中途暂停,只是简单地阻止调度新Operation执行。
继续queue
[queue setSuspended:NO];
关于执行顺序:
对于添加到queue中的operations,它们的执行顺序取决于2点:
1.首先看看NSOperation是否已经准备好:是否准备好由对象的依赖关系确定
2.然后再根据所有NSOperation的相对优先级来确定。优先级等级是operation对象本身的一个属性。默认所有operation都拥有“普通”优先级,不过可以通过setQueuePriority:方法来提升或降低operation对象的优先级。优先级只能应用于相同queue中的operations。如果应用有多个operation queue,每个queue的优先级等级是互相独立的。因此不同queue中的低优先级操作仍然可能比高优先级操作更早执行。
注意:优先级不能替代依赖关系,优先级只是对已经准备好的 operations确定执行顺序。先满足依赖关系,然后再根据优先级从所有准备好的操作中选择优先级最高的那个执行。
3)GCD
GCD的底层依然是用线程实现,让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
GCD使用场景一:单例
+ (instancetype)defaultViewController {
static ViewController *vc = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
vc = [[ViewController alloc] init];
});
return vc;
}
GCD常用场景二:图片异步加载的实现
- (IBAction)handleGCD:(id)sender {
//通过GCD开子线程,执行图片加载(URL)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSURL*url = [NSURLURLWithString:@"http://img5.cache.netease.com/3g/2015/10/30/20151030124521c1f7e.jpg"];
NSData*data = [NSDatadataWithContentsOfURL:url];
UIImage*image = [UIImageimageWithData:data];
// GCD返回主线程UI赋值
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image= image;
});
});
}
管理
GCD核心是队列管理,和NSOperationQueue很相似,但GCD是函数实现,效率高推荐使用
GCD的队列分两种类型,串行,并行
GCD中自带一个串行队列(即主队列-主线程)
GCD中自带4个并行队列(通过get_global...)
a.获取GCD的主队列(串行队列)
//获取GCD的主队列(串行队列)
dispatch_queue_t mainqueue = dispatch_get_main_queue();
dispatch_sync(mainqueue, ^{
[selfsnippet];
});
b.获取GCD自带的并行队列
//获取GCD自带的并行队列
dispatch_queue_t globelQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//向队列中异步分发任务
dispatch_async(globelQueue, ^{
[selfsnippet];
});
c.手动创建串行队列
//手动创建串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL);
//异步分发任务
dispatch_async(serialQueue, ^{
[selfsnippet];
});
c.手动创建并行队列
//手动创建并行队列
dispatch_queue_tandQueue =dispatch_queue_create("com.baidu.www",DISPATCH_QUEUE_CONCURRENT);
//异步分发任务
dispatch_async(andQueue, ^{
[selfsnippet];
});