NSThread适合轻量级的多线程开发,控制线程顺序比较难,同时线程总数无法控制(每次创建并不能重用之前的线程,只能创建新的线程)
1.初始化
- (void)viewDidLoad {
[super viewDidLoad];
//方法一,需要start
NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadAction:) object:@"thread1"];
[thread1 start];
//方法二,需要start
NSThread *thread2 = [[NSThread alloc]initWithBlock:^{
NSLog(@"thread2 - %@",[NSThread currentThread]);
}];
[thread2 start];
//方法三
[NSThread detachNewThreadSelector:@selector(threadAction:) toTarget:self withObject:@"thread3"];
}
-(void)threadAction:(NSString *)string{
NSLog(@"%@ - %@",string,[NSThread currentThread]);
}
//输出结果
2021-05-28 20:49:04.539618+0800 DJGCDDemo[1077:23059] thread2 - <NSThread: 0x6000018f0bc0>{number = 9, name = (null)}
2021-05-28 20:49:04.539612+0800 DJGCDDemo[1077:23058] thread1 - <NSThread: 0x6000018f0180>{number = 8, name = (null)}
2021-05-28 20:49:04.539633+0800 DJGCDDemo[1077:23060] thread3 - <NSThread: 0x6000018f0a80>{number = 10, name = (null)}
2.属性
/**
每个线程都维护了一个键-值的字典,它可以在线程里面的任何地方被访问。
你可以使用该字典来保存一些信息,这些信息在整个线程的执行过程中都保持不变。
比如,你可以使用它来存储在你的整个线程过程中Run loop里面多次迭代的状态信息。
NSThread实例可以使用一下方法
*/
@property (readonly, retain) NSMutableDictionary *threadDictionary;
/**
优先级
*/
@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;
3.实例方法
/**
启动线程
*/
-(void)start;
/**
是否为主线程
*/
-(BOOL)isMainThread;
/**
取消线程
*/
-(void)cancel;
/**
线程的入口函数
*/
-(void)main;
/**
判断线程是否正在执行
*/
-(void)isExecuting;
/**
判断线程是否已经结束
*/
-(void)isFinished;
/**
判断线程是否撤销
*/
-(void)isCancelled;
4.类方法
/**
block方式
*/
+ (void)detachNewThreadWithBlock:(void (^)(void))block;
/**
SEL方式
*/
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
/**
获取当前线程
*/
+(void)currentThread;
/**
当前代码运行所在线程是否是子线程
*/
+(BOOL)isMultiThreaded;
/**
前代码所在线程睡到指定时间
*/
+(void)sleepUntilDate:(NSDate *)date;
/**
当前线程睡多长时间
*/
+(void)sleepForTimeInterval:(NSTimeInterval)ti;
/**
退出当前线程
*/
+(void)exit;
/**
设置当前线程优先级
*/
+(double)threadPriority;
/**
给当前线程设定优先级,调度优先级的取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高
*/
+(BOOL)setThreadPriority:(double)p;
/**
线程的调用都会有函数的调用函数的调用就会有栈返回地址的记录,在这里返回的是函 数调用返回的虚拟地址,说白了就是在该线程中函数调用的虚拟地址的数组
*/
+(NSArray *)callStackReturnAddresses;
/**
同上面的方法一样,只不过返回的是该线程调用函数的名字数字
*/
+(NSArray *)callStackSymbols;
callStackReturnAddress
和callStackSymbols
这两个函数可以同NSLog联合使用来跟踪线程的函数调用情况,是编程调试的重要手段
5.隐式创建
以下方法位于NSObject (NSThreadPerformAdditions)分类中,所有继承NSObject 实例化对象都可调用以下方法。
/**
指定方法在主线程中执行
参数1. SEL方法
2.方法参数
3.是否等待当前执行完毕
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;
/**
指定方法在某个线程中执行
参数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));
/**
指定方法在开启的子线程中执行
参数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));
6.线程间通信
NSThread靠NSObject分类的方法实现线程间通信。
- (void)viewDidLoad {
[super viewDidLoad];
NSThread *thread1 = [[NSThread alloc]initWithBlock:^{
NSLog(@"thread1 - %@",[NSThread currentThread]);
//回到主线程更新UI
[self performSelectorOnMainThread:@selector(updateUI) withObject:self waitUntilDone:YES];
}];
[thread1 start];
}
-(void)updateUI{
NSLog(@"回到主线程更新UI - %@",[NSThread currentThread]);
}
//输出结果
2021-05-28 21:28:35.548572+0800 DJGCDDemo[1361:48398] thread1 - <NSThread: 0x600000336880>{number = 8, name = (null)}
2021-05-28 21:28:35.552002+0800 DJGCDDemo[1361:48233] 回到主线程更新UI - <NSThread: 0x600000374a40>{number = 1, name = main}
网友评论