本文共 3857 字,大约阅读时间需要 12 分钟。
在java里面接触的线程比较熟悉,所以今天转过来学习ios的线程变成
ios的线程分为3种,我就从最底层的NSThread开始学习(越高层越好,苹果也推荐使用更加抽象的高层来编程),使用NSThread管理多个线程仍然是件令人头疼的事情,但是作为学习应该了解下
1.创建线程
NSThread *thread2 = [NSThread detachNewThreadSelector:(SEL) toTarget:(id) withObject:(id)]; NSThread *thread3 = [[NSThread alloc]initWithTarget:(id) selector:(SEL) object:(id)];thread2创建之后就执行了,但是thread3需要[thread start]才能运行
thread2第一个参数标明线程需要处理的方法,第二个参数是线程处理的方法要返回给谁,第三个参数表示要给线程处理的方法传递的对象
thread3第一个参数线程处理的方法要返回给谁,第二个参数方法,第三个参数想方法传递的参数
另外NSObject还有一些隐式调运线程的方法,比如下面的就是隐式的调用主线程的方法
[self performSelectorOnMainThread:@selector(showImg:) withObject:img waitUntilDone:YES];好了,举个例子,来说明如何使用NSThread来下载一张图片并且显示在手机上
下载图片,下载完成之后调用主线程显示图片
-(void)downloadImgWithUrl:(NSString*)url{ NSData *data = [[NSData alloc]initWithContentsOfURL:[[NSURL alloc]initWithString:url]]; UIImage *img = [[UIImage alloc]initWithData:data]; if(img==nil) { NSLog(@"error"); }else { [self performSelectorOnMainThread:@selector(showImg:) withObject:img waitUntilDone:YES]; }}
显示图片,UI的处理都是在主线程上操作的
-(void)showImg:(UIImage*)img{ UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)]; imgView.image = img; [self.view addSubview:imgView];}在viewDidLoad方法中调用线程
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImgWithUrl:) object:@"http://c.hiphotos.baidu.com/image/w%3D2048/sign=4e662d611f950a7b753549c43ee963d9/f31fbe096b63f624690e4f548544ebf81a4ca311.jpg"]; [thread start];结果如下
2.NSOperation用来操作线程,他有两个子类我们可以直接实例化这些子类来操作线程(NSInvocationOperation和NSBlockOperation,NSOperation和NSOperationQueue是更高级别的类,他们大大简化了处理多个线程的过程。)在MacOSXv10.6和iOS4之前,NSOperation与NSOperationQueue不同于GCD,他们使用了完全不同的机制。从MacOSXv10.6和iOS4开始,NSOperation和NSOperationQueue是建立在GCD上的。作为一种通例,苹果推荐使用最高级别的抽象,然而当评估显示有需要时,会突然降到更低级别。
以下是对两者的快速比较,它会帮助你决定何时何地去使用GCD或者NSOperation和NSOperationQueue;
GCD是一种轻量级的方法来代表将要被并发执行的任务单位。你并不需要去计划这些任务单位;系统会为你做计划。在块(block)中添加依赖会是一件令人头疼的事情。取消或者暂停一个块会给一个开发者产生额外的工作! NSOperation和NSOperationQueue对比GCD会带来一点额外的系统开销,但是你可以在多个操作(operation)中添加附属。你可以重用操作,取消或者暂停他们。NSOperation和是兼容的;例如,你可以通过监听NSNotificationCenter去让一个操作开始执行。(1)下面我们用NSInvocationOperation来实现一个例子,用于来显示欢迎某人
- (void)viewDidLoad{ NSInvocationOperation *operatrion = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(showName:) object:@"iked"]; NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [queue addOperation:operatrion];}在线程完成之后调用主线程
-(void)showName:(NSString *)name{ NSString *str = [[NSString alloc]initWithFormat:@"hello %@",name]; [self performSelectorOnMainThread:@selector(showHello:) withObject:str waitUntilDone:YES];}
-(void)showHello:(NSString*)content{ UILabel *lable =[[UILabel alloc]initWithFrame:CGRectMake(20, 50, 150, 80)]; lable.text = content; lable.textColor = [UIColor blackColor]; [self.view addSubview:lable];}
(2)使用NSOperation,操作步骤
1.继承NSOperation类 2.重写“main”方法 3.在“main”方法中创建一个“autoreleasepool”(创建你自己的自动释放池的原因是,你不能访问主线程的自动释放池,所以你应该自己创建一个) 4.将你的代码放在“autoreleasepool”中
在线程操作中,你从来都不能明确知道,一个操作什么时候会开始,要持续多久才能结束。在大多数时候,如果用户滑动离开了页面,你并不想在后台执行一个操作 – 没有任何的理由让你去执行。这里关键是要经常地检查NSOperation类的isCancelled属性。
-(void)main{ @autoreleasepool { for(int i = 0;i<20;i++) { if(self.isCancelled) { break; } NSLog(@"%d",i); } }}当然在调用的时候和它的子类调用是类似的
IKEDImgLoadOperation *operation =[[IKEDImgLoadOperation alloc]init]; NSOperationQueue *queue = [[NSOperationQueue alloc]init]; [queue addOperation:operation];
补充
NSOperationQueue会选择去运行任何数量的并发操作,但是不会超过最大值。
myQueue.MaxConcurrentOperationCount = 3;
每个NSOperation都有一个start方法,但是进入队列之后每个start方法何时调用就是有NSOperationQueue决定了。
转载地址:https://blog.csdn.net/xiaoji94shen/article/details/20994737 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!