NSThread API

//类方法:创建一个线程
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)); //类方法:直接创建并启动线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument; // 判断当前线程是否是多线程
+ (BOOL)isMultiThreaded; //返回线程对象的字典
@property (readonly, retain) NSMutableDictionary *threadDictionary; //阻塞(暂停)线程
+ (void)sleepUntilDate:(NSDate *)date; // 使当前线程睡眠指定的时间,单位为秒
+ (void)sleepForTimeInterval:(NSTimeInterval)ti; // 退出当前线程
+ (void)exit; //线程的调度优先级,取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高
+ (double)threadPriority;
+ (BOOL)setThreadPriority:(double)p;
// To be deprecated; use qualityOfService below 设置优先级程度在iOS8.0之后,建议使用qualityOfService属性
@property double threadPriority NS_AVAILABLE(10_6, 4_0); //NSQualityOfService是个枚举,取值有如下优先级从高到低五种:
//1.NSQualityOfServiceUserInteractive = 0x21 最高:主要用于与UI交互的操作,各种事件处理以及绘制图像等。
//2.NSQualityOfServiceUserInitiated = 0x19 次高:执行一些明确需要立即返回结果的任务。例如,用户在邮件列表中选择邮件后加载电子邮件。
//3.NSQualityOfServiceDefault = -1 默认:默认的优先级,介于次高级和普通级之间。
//4.NSQualityOfServiceUtility = 0x11 普通:用于执行不许要立即返回结果、耗时的操作,下载或者一些媒体操作等。
//5.NSQualityOfServiceBackground = 0x09 后台:后台执行一些用户不需要知道的操作,它将以最有效的方式运行。例如一些预处理的操作,备份或者同步数据等等。
@property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0); //线程的名字 用于区分线程
@property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
//接收器的堆栈大小,以字节为单位
@property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0); //是否为主线程
@property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0); //实例方法,可以获得线程对象
- (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)); //当前线程对象是否正在执行任务
@property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0);
//当前线程对象是否已执行完任务
@property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);
//当前线程对象是否被取消
@property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);
//取消当前线程
- (void)cancel NS_AVAILABLE(10_5, 2_0);
// 开启线程
- (void)start NS_AVAILABLE(10_5, 2_0); // thread body method
//You should never invoke this method directly. You should always start your thread by invoking the start method.这个方法是线程的入口函数,当线程开启,默认会调用这个方法,并将线程入口函数selector和target传入,在该方法中对target调用selector。默认情况下,调用完毕,线程就被自动关闭了 - (void)main NS_AVAILABLE(10_5, 2_0); //这个通知只会被NSThread触发一次,条件是当第一个进程在调用了start或者detachNewThreadSelector:toTarget:withObject:方法.这个通知的接收者的一些处理方法都是在主线程上进行的;这是因为这个通知是在系统生产新的子线程之前进行的,所以在监听这个通知的时候,调用监听者的通知方法都会在主线程进行.
FOUNDATION_EXPORT NSNotificationName const NSWillBecomeMultiThreadedNotification; //这个通知目前没有实际意义,苹果也仅仅是保留这个扩展通知而已,并没有在NSThread的方法中,来触发这个消息,不过根据这个通知的字面意思来理解,是进程又回到单一线程的时候,会发送这个通知;但在多线程环境下, 这个没有什么实际的处理工作,可暂时忽略;
FOUNDATION_EXPORT NSNotificationName const NSDidBecomeSingleThreadedNotification; //在线程被终止前会发送NSThreadWillExitNotification通知给通知中心。由于通知是同步发送的,因此可以确保在线程终止前,通知中心已经收到通知了。应该慎重调用这个方法,因为它无法保证资源的释放,造成内存泄露。
FOUNDATION_EXPORT NSNotificationName const NSThreadWillExitNotification; //线程间通信的方法
//多了一个modes参数,是用来设置runLoop模式
- (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; //可以从任意的两个线程之间作转换
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
//隐式创建并启动线程
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);

实例运用及理解说明

1.创建线程的几种方式

//几种创建分线程的方式
//1.实例方法,需要手动开启线程,可以设置线程的更多属性
NSThread *threadOne = [[NSThread alloc]initWithTarget:self selector:@selector(startANewThreadOne:) object:nil];
[threadOne start]; //2.类方法,自动开启线程,不可设置线程更多属性
[NSThread detachNewThreadSelector:@selector(startANewThreadTwo:) toTarget:self withObject:nil]; //3.隐式创建方法
[self performSelectorInBackground:@selector(startANewThreadThree:) withObject:nil]; //4.ios10之后可以使用
NSThread *threadFour = [[NSThread alloc]initWithBlock:^{
//在此执行耗时操作
}];
[threadFour start]; //5.ios10之后可以使用 NSThreadWillExitNotification监听不到线程执行完毕
[NSThread detachNewThreadWithBlock:^{
//执行耗时操作
}];

2.相关属性及API简单使用

- (void)viewDidLoad {
[super viewDidLoad]; //监听线程退出的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(threadWillExitNotice) name:NSThreadWillExitNotification object:nil]; //注意:线程的生命周期,当线程中的任务执行完成之后被释放掉
NSThread *threadOne = [[NSThread alloc]initWithTarget:self selector:@selector(startANewThreadOne:) object:@"分线程一"];
threadOne.name = @"threadOne";
threadOne.qualityOfService = NSQualityOfServiceUserInitiated;
NSMutableDictionary *dic = threadOne.threadDictionary;
[dic setObject:@"Bob" forKey:@"name"];
[dic setObject:@"" forKey:@"age"];
[threadOne start]; } -(void)startANewThreadOne:(id)param { if ([NSThread isMultiThreaded]) { for (int i = ; i < ; i++) {
NSLog(@"耗时操作 %d",i);
if (i == ) {
NSLog(@"睡会在干");
[NSThread sleepForTimeInterval:];
}
} NSThread *thread = [NSThread currentThread];
NSLog(@"-----> %@",thread.threadDictionary);
} }

3.线程的状态

init 后会创建一个线程对象,此时线程处于新建New的状态,调用start方法后,会将线程加入到可调度线程池中,此时进入就绪Runnable状态,当CPU调度到当前线程的时候,这时就会处于运行Running的状态,当CPU调度其他线程的时候,当前线程又回到就绪状态,当我们对当前线程调用了sleep或者等待同步锁的时候,此时又会进入线程阻塞Blocked状态, 这时线程对象会被移除可调度线程池,但还存在内存中,当时间到了的时候,重新进入到就绪状态,加入到可调度线程池中,当任务执行完毕或强制退出后,进入到死亡Dead状态,此时线程对象被释放

4.线程安全

多条线程抢夺同一块资源,可能会导致数据错乱和数据安全的问题。解决:互斥锁,加锁可以使线程同步(多条线程在同一条线上按顺序的执行任务)同时需要耗费性能

优点:有效防止因多线程抢夺资源造成的数据安全问题

缺点:需要消耗大量的CPU资源

- (void)viewDidLoad {
[super viewDidLoad]; _ticketCount = ;//票的总量 NSThread *threadOne = [[NSThread alloc]initWithTarget:self selector:@selector(startSellTickets) object:nil];
threadOne.name = @"售票员1";
[threadOne start]; NSThread *threadTwo = [[NSThread alloc]initWithTarget:self selector:@selector(startSellTickets) object:nil];
threadTwo.name = @"售票员2";
[threadTwo start]; NSThread *threadThree = [[NSThread alloc]initWithTarget:self selector:@selector(startSellTickets) object:nil];
threadThree.name = @"售票员3";
[threadThree start]; }
- (void)startSellTickets { while () { //self : 锁对象,必须全局唯一,一般选择填self
@synchronized (self) { if (_ticketCount > ) { [NSThread sleepForTimeInterval:0.3];//模拟卖票的耗时操作
_ticketCount--;
NSLog(@"%@卖出去一张票,还剩%d张票",[NSThread currentThread].name,_ticketCount);
}else{
NSLog(@"end");
break;
}
} } }

卖票实例

5.原子和非原子属性

atomic:原子属性,线程安全,需要消耗大量的资源,为setter方法加锁(默认就是atomic)

nonatomic:非原子属性,非线程安全,适合内存小的移动设备

原文地址:去查看

//@property(nonatomic, retain) UITextField *userName;
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
} //@property(retain) UITextField *userName;
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}
- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName release];
userName = [userName_ retain];
}
}

6.线程间的通信

一个线程传递数据给另一个线程,在一个线程中执行完特定任务后,转到另一个线程继续执行任务,比如:在子线程中下载图片,在回到主线程展示图片

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

以上博文如有理解有误的地方,欢迎指正!









最新文章

  1. NOIP2014初赛分数线及金华上线名单
  2. 关于《hibernate多对多》有中间表的建立
  3. PHP上传大文件 分割文件上传
  4. C++ 约瑟夫环问题
  5. USB的四种传输类型
  6. Windows Phone8开发工具包简述(转载)
  7. 10款AJAX/CSS/HTML的在线表单生成器
  8. PHP中字符串补齐为定长
  9. poj 2309
  10. struts OGNL数据标签
  11. FLOYD 求最小环
  12. 团队作业4——第一次项目冲刺(Alpha版本) 4.24
  13. 如何简单地理解Python中的if __name__ == &#39;__main__&#39;
  14. Spring AOP详细介绍
  15. 我为什么要选择RabbitMQ ,RabbitMQ简介,各种MQ选型对比(转载)
  16. Unittest + python
  17. Eclipse中JSP生成的class文件去了哪里?
  18. iis部署webservice问题集合
  19. Qt ------ 截图、获取鼠标指定的RGB值
  20. 30分钟LINQ教程的学习笔记

热门文章

  1. PAT 天梯赛 L1-054. 福到了 【字符串】
  2. ubuntu动态加载模块简单模板
  3. [bzoj1002] [FJOI2007]轮状病毒轮状病毒(基尔霍夫矩阵)
  4. Linux下直接读写物理地址内存
  5. 很好的 DHCP协议与dhcpcd分析【转】
  6. HDU1102 Constructing Roads —— 最小生成树
  7. 人生苦短之Python多线程
  8. ZIP伪加密(deprecated)
  9. [HNOI 2010] 弹飞绵羊
  10. Linux终端程序用c语言实现改变输出的字的颜色