本文我先来介绍iOS上多线程NSThread实现方式、使用方法、优劣介绍一下。
-
简介:
优点:相较轻量级、使用简单。
缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销。 -
使用方式:
//方式一: [self performSelectorInBackground:@selector(action:) withObject:@"thread"]; //方式二: NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(action:) object:@"text"]; thread.name = @"Thread Name"; [thread start];//开启线程 //方式三: [NSThread detachNewThreadSelector:@selector(action:) toTarget:self withObject:@"thread2"]; //方式四: //回到主线程 [self performSelectorOnMainThread:@selector(action:) withObject:nil waitUntilDone:YES]; //方式五: + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
-
长周期线程:
在线程启动之后会首先执行-threadMain,正常情况下threadMain方法执行结束之后,线程就会退出。为了线程可以长期复用接收消息,我们需要在threadMain中给thread添加runloop
- (void)threadAction { [[NSThread currentThread] setName:@"myThread"]; // ①给线程设置名字 NSRunLoop *runLoop = [NSRunLoop currentRunLoop];// ②给线程添加runloop [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; //③给runloop添加数据源 while (![[NSThread currentThread] isCancelled]) {//④:检查isCancelled [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; //⑤启动runloop } } //添加任务 [self performSelector:@selector(threadTask) onThread:self.thread withObject:nil waitUntilDone:NO]; //结束任务 - (void)cancelThread { [[NSThread currentThread] cancel]; CFRunLoopStop(CFRunLoopGetCurrent()); }
-
优先级:
每个线程的紧急程度是不一样的,有的线程中任务你也许希望尽快执行, 有的线程中任务也许并不是那么紧急,所以线程需要有优先级。 优先级高线程中 的任务会比优先级低的线程先执行 NSThread有4个优先级的API + (double)threadPriority; + (BOOL)setThreadPriority:(double)p; @property double threadPriority NS_AVAILABLE(10_6, 4_0); // To be deprecated; use qualityOfService below @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0); // read-only after the thread is started 前2个是类方法,用于设置和获取当前线程的优先级 threadPriority属性可以通过对象设置和获取优先级 由于线程优先级是一个比较抽线的东西,没人能知道0.5和0.6到底有多大区别,所以iOS8之后新增了qualityOfService枚举属性,大家可以通过枚举值设 置优先级 typedef NS_ENUM(NSInteger, NSQualityOfService) { NSQualityOfServiceUserInteractive = 0x21, NSQualityOfServiceUserInitiated = 0x19, NSQualityOfServiceDefault = -1 NSQualityOfServiceUtility = 0x11, NSQualityOfServiceBackground = 0x09, } NSQualityOfService: NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操作,比如处理点击事件,绘制图像到屏幕上 NSQualityOfServiceUserInitiated:次高优先级,主要用于执行需要立即返回的任务 NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级 NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务 NSQualityOfServiceBackground:后台优先级,用于完全不紧急的任务
-
其他:
//获取当前线程 NSThread *thread = [NSThread currentThread]; //判断当前是否在多线程 + (BOOL)isMultiThreaded; //判断当前是否在主线程 [NSThread isMainThread]; //让当前线程睡眠到date + (void)sleepUntilDate:(NSDate *)date; //让当前线程睡眠几秒 + (void)sleepForTimeInterval:(NSTimeInterval)ti; //退出当前子线程 + (void)exit; //获取当前线程栈大小,默认开辟512K、最小为8K、分配时为4的倍数 NSLog(@"%tu", [NSThread currentThread].stackSize / 1024); //设置当前线程栈大小 [NSThread currentThread].stackSize = 4 * 1024;
-
通知:
//由当前线程派生出第一个其他线程时发送,一般一个线程只发送一次 NSWillBecomeMultiThreadedNotification; // NSDidBecomeSingleThreadedNotification; //退出线程通知 NSThreadWillExitNotification;