在 iOS 中其实目前主流有3种多线程方案,他们分别是:
NSThread
NSOperation & NSOperationQueue
GCD
NSThread
优点:NSThread
比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
NSOperation & NSOperationQueue
优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。
NSOperation
是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation
和NSBlockOperation
。
创建NSOperation
子类的对象,把对象添加到NSOperationQueue
队列里执行
Grand Central Dispatch (GCD)
: 它是苹果为多核的并行运算提出的解决方案,所以会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。
NSThread 案例:
新建文件
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(50, 0,self.view.bounds.size.width, self.view.bounds.size.height)];
scrollView.contentSize =CGSizeMake(1000, 0);
scrollView.backgroundColor = [UIColor grayColor];
[self.view addSubview:scrollView];
UIButton *button = [[UIButton alloc ]initWithFrame:CGRectMake(0, self.view.bounds.size.height-80, 200, 80)];
button.backgroundColor = [UIColor yellowColor];
[scrollView addSubview: button];
[button addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self thread];
}
-(void)thread{
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(btnClick) object:nil];
[thread start];
}
-(void)thread{
//方法1:使用对象方法
//创建一个线程,第一个参数是请求的操作,第二个参数是操作方法的参数
// NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(loadImage) object:nil];
// //启动一个线程,注意启动一个线程并非就一定立即执行,而是处于就绪状态,当系统调度时才真正执行
// [thread start];
//方法2:使用类方法
[NSThread detachNewThreadSelector:@selector(btnClick) toTarget:self withObject:nil];
}
//按钮的点击事件 卡顿事件
- (void)btnClick {
for (int i = 0 ;i<10000 ; i++) {
NSLog(@"btnClick---%d",i);
}
}
测试效果为,运行软件后. 在读数期间能scrollView能向右拉.
而 点击button 后 scrollView不能向右拉.
因为点击button 是属于当前线程.想大量算数的时候回造成卡顿.
而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;
NSOperation & NSOperationQueue案例
创建
在上面的文档中
添加方法
-(void)OperationQueue{
NSInvocationOperation *invocationOpertion =[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(btnClick) object:nil];
//objct 可以穿参数
//创建完NSInvocationOperation对象并不会调用,它由一个start方法启动操作,但是注意如果直接调用start方法,则此操作会在主线程中调用,一般不会这么操作,而是添加到NSOperationQueue中
NSOperationQueue *qperationQueue = [[NSOperationQueue alloc]init];
[qperationQueue addOperation:invocationOpertion];
}
在viewDidLoad下添加[self OperationQueue];
- (void)viewDidLoad {
...
...
[self OperationQueue];
}
运行,效果也是一样上面一样, 在读数期间能scrollView能向右拉.
点击button 后 scrollView不能向右拉.
//设置最大并发线程数
operationQueue.maxConcurrentOperationCount=5;
//创建多个线程用于填充图片
for (int i=0; i<count-1; ++i) {//这个不是加入 我们测试文件
//方法1:创建操作块添加到队列
//创建多线程操作
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
[self loadImage:[NSNumber numberWithInt:i]];
}];
//设置依赖操作为最后一张图片加载操作
[imageOperation addDependency:lasIimageOperation];
还有很多类 .大家多点练习
-NSOperation
BOOL executing; //判断任务是否正在执行
BOOL finished; //判断任务是否完成
void (^completionBlock)(void); //用来设置完成后需要执行的操作
- (void)cancel; //取消任务
- (void)waitUntilFinished; //阻塞当前线程直到此任务执行完毕
NSOperationQueue
NSUInteger operationCount; //获取队列的任务数
- (void)cancelAllOperations; //取消队列中所有的任务
- (void)waitUntilAllOperationsAreFinished; //阻塞当前线程直到此队列中的所有任务执行完毕
[queue setSuspended:YES]; // 暂停queue
[queue setSuspended:NO]; // 继续queue
GCD
因为GCD要做作业下面有传送下
========
||---------||
||--传送门--||
||---------||
部分文章取之文/伯恩的遗产原文链接:
http://www.jianshu.com/p/0b0d9b1f1f19