IOS编程之多线程
目录
- 概述——对多线程的理解
- IOS中实现多线程的三种方式
NSThread
线程创建
线程的同步与锁
线程间的交互
线程的操作方法
NSOperation and NSOperationQueue
GCD(Grand Central Dispatch)
- 线程间的通信
- 解决多个线程同时访问同一个内存资源的问题
- 多线程的运用
卖火车票
- 对多线程底层的可能实现的猜测
概述——对多线程的理解
为了避免在主线程中执行一些任务时可能会出现异常而卡死,我们可以把这些任务放到新的线程中进行执行,即使出现异常,主线程也依旧可以做取消操作的响应;同时,有时我们为了让用户拥有更好的体验,我们也常常把对界面、网络请求和应答等等的处理放到新的线程中进行,而不会因为有时很久的处理而让用户不能去操作其他只能够等待操作完成
IOS中实现多线程的三种方式
NSThread
概述
优缺点
优点:易理解,创建快
缺点:需要写很多相关方法,不便于代码的维护
线程创建
-(id)init;
-(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
注:以上的两种方法创建线程之后需要手动启动,启动方法:-(void)start;
+ (
void
)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument;
注:以上方法直接生产一个线程并启动它
线程的同步与锁
IOS使用NSCondition来进行线程同步,它是IOS的所对象,用来保护当前访问的资源
使用方法
NSCondition *myLock = [[NSCondition alloc] init];
[myLock lock];
资源..
[myLock unLock];
线程间的交互
调用主线程的指定方法来执行相关操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
线程的操作方法
//返回当前线程
+ (NSThread *)currentThread;
// 通过类方法创建一个线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
// 判断是否为多线程
+ (BOOL)isMultiThreaded;
- (NSMutableDictionary *)threadDictionary;
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 退出线程
+ (void)exit;
// 线程属性值
+ (double)threadPriority ;
+ (BOOL)setThreadPriority:(double)p ;
// 线程函数地址
+ (NSArray *)callStackReturnAddresses;
// 设置与返回线程名称
- (void)setName:(NSString *)n;
- (NSString *)name;
// 线程堆栈
- (NSUInteger)stackSize;
- (void)setStackSize:(NSUInteger)s;
// 判断当前线程是否为主线程
- (BOOL)isMainThread;
+ (BOOL)isMainThread;
+ (NSThread *)mainThread;
// 线程对象初始化操作 (通过创建线程对象 ,需要 手工指定线程函数与各种属性)
- (id)init;
// 在线程对象初始化时创建一个线程(指定线程函数)
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
// 是否在执行
- (BOOL)isExecuting;
// 是否已经结束
- (BOOL)isFinished;
// 是否取消的
- (BOOL)isCancelled;
// 取消操作
- (void)cancel;
// 线程启动
- (void)start;
- (void)main; // thread body method
NSOperation and NSOperationQueue
概述
NSInvocationOperation是NSOperation的子类;
NSOperation是不能直接拿来调用的,使用其定义好的子类NSInvocationOperation或者自定义其子类重写main方法;
通过NSOperationQueue中的addOperation:方法来添加操作,然后系统会自动执行相关操作;
队列里可以加入很多个NSOperation, 可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。
通过的代码设置:[queue setMaxConcurrentOperationCount:5];
线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作
操作对象的创建
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector( ) object: ];
将操作对象添加到系统已有的操作队列里,这是是以一个线程的方式与主线程分开执行
[[MyAppDelegate sharedOperationQueue] addOperation:operation];
我们也可以使用NSOperationQueue创建自己的线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount: ];
[operationQueue addOperation:operation];
GCD(Grand Central Dispatch)
概述
优缺点
优点:对相关事件的处理都集中于一个地方,不用写很多个方法去实现某一功能
缺点:代码可读性差
举例
dispatch_async(dispatch_queue_create("threadName",DISPATCH_QUEQU_SERIAL),^{
dispatch_sync(dispatch_get_main_queue( ),^{
//主线程
}
}
注意问题
同步和异步;
什么时候用同步什么时候用异步;
线程数,超出预设的线程数的最大值会怎样,为什么要设线程数;
执行的线程有没有优先级,执行完成有没有先后顺序;
线程间通信;
线程安全,如何让一个方法未执行完之前第二个方法不可以执行;