iOS之多线程---三种多线程技术
2015-10-22 14:32
387 查看
1.多线程的基本概念和用法
①进程:每一个进程都一是一个应用程序,都有独立的内存空间。(一个程序也可以由多个进程)同一个进程中的线程共享内存中的存储空间和资源
②线程:
每一个程序都有一个主线程,调用main来启动。
主线程的生命周期和应用程序绑定,程序退出时主线程停止。
任何可以阻塞主线程的任务不要再主线程中执行(比如访问网络)
2.多线程使用的注意
①线程使用不是无节制的:
iOS中的主线程的堆栈大小是1M(不可变)
从第二个线程开始都是512KB(不可变)
②只有主线程可以修改UI,渲染引擎工作在主线程中
优:量级较轻
缺:需要自己管理线程的生命周期、线程同步、加锁、睡眠和唤醒等,
②NSOperation/NSOperationQueue:面向对象的线程技术
优:不需要关心线程管理、数据同步的事情,且是面向对象的
③GCD(Grand Central Dispatch):是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术
下面对三种技术,用代码逐一讲解:
补充1:线程中的内存管理问题,NSRunloop和如何跳出线程
NSRunloop:
①线程的生命周期存在5个状态:新建、就绪、运行、阻塞、死亡
②NSRunLoop可以保持一个线程一直为活动状态,不会马上销毁掉
③应用举例:多线程中使用定时器时,必须使用Runloop。因为只有开启Runloop保持线程为活动状态,定时器才不会失效
跳出线程方法:
调用cancel方法,然后再线程方法中根据线程的isCancelled属性可以break出线程方法
①跳出单个线程:[thread1 cancel];
②队列中,跳出多个线程:[queue cancelAllOperations];
内存问题:
多线程创建的实例对象不会放入自动释放池,可能会导致内存泄露。需要手动放入自动重生池
举例:创建一个线程队列queue和一个线程类MyOperation,在queue中添加2个继承于MyOperation类的任务,实现以上补充内容中提到的知识点
以下是viewController中的代码:
以下是MyOperation类的具体实现:
①进程:每一个进程都一是一个应用程序,都有独立的内存空间。(一个程序也可以由多个进程)同一个进程中的线程共享内存中的存储空间和资源
②线程:
每一个程序都有一个主线程,调用main来启动。
主线程的生命周期和应用程序绑定,程序退出时主线程停止。
任何可以阻塞主线程的任务不要再主线程中执行(比如访问网络)
2.多线程使用的注意
①线程使用不是无节制的:
iOS中的主线程的堆栈大小是1M(不可变)
从第二个线程开始都是512KB(不可变)
②只有主线程可以修改UI,渲染引擎工作在主线程中
3.IOS的三种多线程技术(本文主题)
①NSThread:每个NSThread对象对应一个线程优:量级较轻
缺:需要自己管理线程的生命周期、线程同步、加锁、睡眠和唤醒等,
②NSOperation/NSOperationQueue:面向对象的线程技术
优:不需要关心线程管理、数据同步的事情,且是面向对象的
③GCD(Grand Central Dispatch):是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术
下面对三种技术,用代码逐一讲解:
①NSThread
- (void)viewDidLoad { [super viewDidLoad]; for (int i=0; i<10; i++) { //1.线程睡眠 [NSThread sleepForTimeInterval:1]; NSLog(@"主线程1: %d", i); } NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thread1:) object:@"multiThread1"]; //2.开始线程 [thread start]; for (int i=0; i<10; i++) { //3.获取当前线程 NSThread *current = [NSThread currentThread]; //4.判断当前线程是否是主线程 BOOL isMain = [current isMainThread]; if (isMain) { NSLog(@"主线程2: %d", i); } } } -(void) thread1:(NSString *) threadName{ for (int i=0; i<10; i++) { NSLog(@"%@: %d", threadName, i); if (i == 5) { //5.退出线程 [NSThread exit]; } } }
②NSOperationQueue
- (void)viewDidLoad { [super viewDidLoad]; //1.创建线程队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //2.创建线程任务 /*NSOperation介绍: 是Cocoa中的一个抽象类,用来封装单个任务和代码执行一项操作,由于是抽象类,所以不能直接实例化使用,必须定义子类继承该抽象类来实现(常用的为NSInvocationOperation类,但是也可以自己继承重写NSOperation类) */ NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread1:) object:@"thread1"]; NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread2:) object:@"thread2"]; //3.设置队列属性 //1)设置并发数量 queue.maxConcurrentOperationCount = 1; //2)暂停线程 queue.suspended = YES; //3)设置线程优先级,需要先暂停线程才会生效 op1.queuePriority = NSOperationQueuePriorityHigh; op2.queuePriority = NSOperationQueuePriorityVeryLow; //4.任务完成时调用block op1.completionBlock = ^{ NSLog(@"op1已经完成"); }; //5.创建任务的另一种方法:block方式 [queue addOperationWithBlock:^{ //也是一个线程入口,和op1、op2一样是一个线程 for (int k=0; k<10; k++) { NSLog(@"blockThread: %d", k); } }]; [queue addOperation:op2]; [queue addOperation:op1]; //6.开始线程 queue.suspended = NO; for (int k=0; k<10; k++) { NSLog(@"main: %i", k); } } -(void) thread1:(NSString *) threadName { for (int i=0; i<10; i++) { NSLog(@"%@: %d", threadName, i); } } -(void) thread2:(NSString *) threadName { for (int j=0; j<10; j++) { NSLog(@"%@: %d", threadName, j); } }
③GCD
传送门:http://blog.csdn.net/u012526801/article/details/49004871补充1:线程中的内存管理问题,NSRunloop和如何跳出线程
NSRunloop:
①线程的生命周期存在5个状态:新建、就绪、运行、阻塞、死亡
②NSRunLoop可以保持一个线程一直为活动状态,不会马上销毁掉
③应用举例:多线程中使用定时器时,必须使用Runloop。因为只有开启Runloop保持线程为活动状态,定时器才不会失效
跳出线程方法:
调用cancel方法,然后再线程方法中根据线程的isCancelled属性可以break出线程方法
①跳出单个线程:[thread1 cancel];
②队列中,跳出多个线程:[queue cancelAllOperations];
内存问题:
多线程创建的实例对象不会放入自动释放池,可能会导致内存泄露。需要手动放入自动重生池
举例:创建一个线程队列queue和一个线程类MyOperation,在queue中添加2个继承于MyOperation类的任务,实现以上补充内容中提到的知识点
以下是viewController中的代码:
- (void)viewDidLoad { [super viewDidLoad]; _queue = [[NSOperationQueue alloc] init]; _op1 = [[MyOperation alloc] initwithName:@"thread1"]; _op2 = [[MyOperation alloc] initwithName:@"thread2"]; [_queue addOperation:_op1]; [_queue addOperation:_op2]; _op1.completionBlock = ^ { NSLog(@"op1已经完成------------------"); }; _op2.completionBlock = ^ { NSLog(@"op2已经完成------------------"); }; // [self performSelector:@selector(afterDelay) withObject:nil afterDelay:0.1]; [self performSelector:@selector(cancelAllThread) withObject:nil afterDelay:0.5]; } -(void) afterDelay { [_op1 cancel]; } -(void) cancelAllThread { [_queue cancelAllOperations]; }
以下是MyOperation类的具体实现:
#import <Foundation/Foundation.h> @interface MyOperation : NSOperation @property (nonatomic, copy) NSString *mask; -(instancetype) initwithName:(NSString *)mask; @end //############################################################## #import "MyOperation.h" @implementation MyOperation -(instancetype) initwithName:(NSString *)mask { if (self == [super init]) { _mask = mask; } return self; } -(void) main { //1.多线程创建的实例对象不会放入自动释放池,可能会导致内存泄露。需要手动放入自动重生池 @autoreleasepool { [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeAction) userInfo:nil repeats:YES]; //2.开启Runloop来保持线程的存活状态 [[NSRunLoop currentRunLoop] run]; for (int i=0; i<1000; i++) { //3.cancel方法只是改变isCancelled属性,在线程实现方法中做判断,用于跳出线程方法。 if (self.isCancelled) { break; } NSLog(@"%@: %d", self.mask, i); } } } -(void) timeAction { } @end
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- C#控制台下测试多线程的方法
- Ruby 多线程的潜力和弱点分析