【iOS】从实际出发理解多线程(二)--NSThread基础操做

简介ios

NSthread是苹果官方提供面向对象操做线程的技术,简单方便,能够直接操做线程对象,不过须要本身控制线程的生命周期。在平时使用较少,经常使用的就是下面的方法来获取当前线程。macos

[NSThread currentThread]

使用编程

1.实例初始化、属性和实例方法数组

初始化函数

切记下面两个方法初始化的NSThread必须手动start开启线程
//建立线程
NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"Thread"];
//或者
NSThread  *newThread=[[NSThread alloc]init];
NSThread  *newThread= [[NSThread alloc]initWithBlock:^{
  NSLog(@"initWithBlock");
}];

属性oop

线程字典ui

/**
每一个线程都维护了一个键-值的字典,它能够在线程里面的任何地方被访问。
你可使用该字典来保存一些信息,这些信息在整个线程的执行过程当中保持不变。
好比,你可使用它来存储在你的整个线程过程当中 Run loop 里面屡次迭代的状态信息。
NSThread实例可使用如下方法
*/

@property (readonly, retain) NSMutableDictionary *threadDictionary;
NSMutableDictionary *dict = [thread threadDictionary];  

 

优先级spa

@property double threadPriority ; //优先级

线程优先级线程

/** NSQualityOfService:
  NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操做,好比处理点击事件,绘制图像到屏幕上
  NSQualityOfServiceUserInitiated:次高优先级,主要用于执行须要当即返回的任务
  NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级
  NSQualityOfServiceUtility:普通优先级,主要用于不须要当即返回的任务
  NSQualityOfServiceBackground:后台优先级,用于彻底不紧急的任务
*/
@property NSQualityOfService qualityOfService

线程名称调试

@property (nullable, copy) NSString *name;

线程使用栈区大小,默认是512k

@property NSUInteger stackSize ;

线程状态(正在执行、执行结束、是否能够取消)

@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;

实例方法

// 启动线程  实例化线程须要手动启动才能运行
- (void)start;
[thread stary]


// 是否为主线程
- (BOOL)isMainThread; 
isMain = [thread isMainThread];

//设置线程名称
- (void)setName:(NSString *) name;
[thraed setName:@"name"];

// 取消线程 
- (void)cancel;
[thread  cancel];

// 线程的入口函数
- (void)main; 
[thread main];

// 线程是否正在执行
- (void)isExecuting;
isRunning=[thread isExecuting];

// 线程是否已经结束
- (void)isFinished;
isEnd=[thread isFinished];

// 线程是否撤销
- (void)isCancelled;
isCancel=[thread isCancelled];

类建立方法

/*
   建立子线程并开始
   建立后就可执行,不须要手动开启
可是不能获取NSThread对象
*/ /** block方式 具体的任务在Block中执行 */ + (void)detachNewThreadWithBlock:(void (^)(void))block; /** SEL方式 利用selector方法初始化NSThread,target指selector方法从属于的对象 selector方法也 是指定的target对象的方法 */ + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

类使用方法

// 获取当前线程
+ (void)currentThread;
[NSThread currentThread];

//当前代码运行所在线程是否为子线程
+ (BOOL)isMultiThreaded;
isMulti = [NSThread isMultiThreaded];

// 当前代码所在线程睡到指定时间  
+ (void)sleepUntilDate: (NSDate *)date; 
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

// 线程沉睡时间间隔,这个方法在设置启动页间隔的时候比较常见
+ (void)sleepForTimeInterval: (NSTimeInterval)time;
[NSThread sleepForTimeInterval:1.0];

// 退出当前线程
+ (void)exit;
[NSThread exit];

// 设置当前线程优先级
+ (double)threadPriority;
double dPriority=[NSThread threadPriority];

// 给当前线程设定优先级,调度优先级的取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高。
+ (BOOL)setThreadPriority:(double)priority;
BOOL isSetting=[NSThread setThreadPriority:(0.0~1.0)];

// 线程的调用都会有行数的调用函数的调用,就会有栈返回地址的记录,
在这里返回的是函数调用返回的虚拟地址
说白了就是在在该先出中函数调用的虚拟地址的数组
+ (NSArray *)callStackReturnAddresses;
NSArray *addressArray=[NSThread callStackReturnAddresses];

// 同上面的方法同样,只不过返回的是该线程调用函数的名字数字
+ (NSArray *)callStackSymbols;
NSArray* nameNumArray=[NSThread callStackSymbols];

注意:callStackReturnAddress和callStackSymbols这两个函数能够同NSLog联合使用来跟踪线程的函数调用状况,是编程调试的重要手段

 隐式建立&线程间通信

如下方法位于NSObject(NSThreadPerformAdditions)分类中,全部继承自NSObject实例化对象均可以调用如下方法。

/**
  指定方法在主线程中执行
  参数1. SEL 方法
    2.方法参数
    3.BOOL类型  表示是否等待当前aSelector方法执行完毕
    4.指定的Runloop model
*/
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes
/**
  指定方法在某个线程中执行
  参数1. SEL 方法
    2.方法参数
    3.是否等待当前执行完毕
    4.指定的Runloop model
*/
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    // equivalent to the first method with kCFRunLoopCommonModes
/**
  指定方法在开启的子线程中执行
  参数1. SEL 方法
    2.方法参数
*/
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

注意:咱们提到的线程间通信就是这几个方法,没有多高大上多复杂。

再注意:苹果声明UI更新必定要在UI线程(主线程)中执行,虽然不是全部后台线程更新UI都会出错。

再注意:waitUntilDone后面的这个BOOL类型的参数,这个参数的意义有点像咱们是否同步执行aSelector这个任务!具体的看下面两张图的内容就一目了然了。

 

 

相关文章
相关标签/搜索