iOS多线程-NSThread

一、基本概念

1.计算机操作系统都有的基本概念,以下概念简单方式来描述。

1 进程: 一个具有一定独立功能的程序关于某个数据集合的一次运行活动。可以理解成一个运行中的应用程序。
2 线程: 程序执行流的最小单元,线程是进程中的一个实体。
3 队列: 装载线程任务的队形结构。

2.苹果官方定义

The term thread is used to refer to a separate path of execution for code.
The term process is used to refer to a running executable, which can encompass multiple threads.

线程用于指代一个独立执行的代码路径
进程用于指代一个可执行程序,他可以包含多个线程

Paste_Image.png

3.同步和异步主要影响:能不能开启新的线程

1 同步:只是在当前线程中执行任务,不具备开启新线程的能力
2 异步:可以在新的线程中执行任务,具备开启新线程的能力

4.并发和串行主要影响:任务的执行方式

1 并发:多个任务并发(同时)执行
2 串行:一个任务执行完毕后,再执行下一个任务

注意:
  1. 一个进程可有多个线程。
  2. 一个进程可有多个队列。
  3. 队列可分并发队列和串行队列。

二.NSThread API

1. 线程创建的两种方式
//直接创建并启动一个线程去Selector
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
//线程创建出来之后需要手动调用-start方法启动
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);

2. 线程操作之------启动,睡眠,取消,退出

Paste_Image.png
1. 启动
使用init方式创建需要手动- (void)start;

例子-

//init初始化
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread:) object:@"thread"];
// 开启线程
[thread start];

例子二

//创建并自动开启方法
[NSThread detachNewThreadSelector:@selector(thread1:) toTarget:self withObject:@"thread1"];

2. 线程睡眠的两种方法
//根据NSDate传入睡眠时间
+ (void)sleepUntilDate:(NSDate *)date;
//直接传入NSTimeInterval
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

NSThread的sleepUntilDate与runloop的runUntilDate:
深入理解RunLoop

![1.jpg](http://upload-images.jianshu.io/upload_images/326255-a503a03b9938f3ad.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

sleepUntilDate:相当于执行一个sleep的任务。在执行过程中,即使有其他任务传入runloop,runloop也不会立即响应,必须sleep任务完成之后,才会响应其他任务
runUntilDate:虽然会阻塞线程,阻塞过程中并不妨碍新任务的执行。当有新任务的时候,会先执行接收到的新任务,新任务执行完之后,如果时间到了,再继续执行runUntilDate:之后的代码

例子:

//让线程睡眠2秒(阻塞2秒)
[NSThread sleepForTimeInterval:2];
//直接传入NSTimeInterval

[NSThread sleepUntilDate:[NSDate datewithTimeIntervalSinceNow:2]];

3.取消

对于线程的取消,NSThread提供了一个取消的方法和一个属性,调用-cancel方法并不会立刻取消线程,它仅仅是将cancelled属性设置为YES。cancelled也仅仅是一个用于记录状态的属性。线程取消的功能需要我们在main函数中自己实现

- (void)cancel NS_AVAILABLE(10_5, 2_0);

要实现取消的功能,我们需要自己在线程的main函数中定期检查isCancelled状态来判断线程是否需要退出,当isCancelled为YES的时候,我们手动退出。如果我们没有在main函数中检查isCancelled状态,那么调用-cancel将没有任何意义

5.退出

与充满不确定性的-cancel相比,-exit函数可以让线程立即退出。

+ (void)exit;

-exit属于核弹级别终极API,调用之后会立即终止线程,即使任务还没有执行完成也会中断。这就非常有可能导致内存泄露等严重问题,所以一般不推荐使用。

三. 线程之间的通讯

1. 从主线程把耗时的任务丢给辅助线程,当任务完成之后辅助线程再把结果传回主线程传,这些线程通讯一般用的都是perform方法
//将selector丢给主线程执行,可以指定runloop mode
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array; 

//将selector丢给主线程执行,runloop mode默认为common mode
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait; 
 
//将selector丢个指定线程执行,可以指定runloop mode
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array NS_AVAILABLE(10_5, 2_0);

//将selector丢个指定线程执行,runloop mode默认为default mode
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);


2. 主线程相关

// 获得主线程
+ (NSThread *)mainThread;

// 是否为主线程
- (BOOL)isMainThread;

// 是否为主线程
+ (BOOL)isMainThread;
// 获得当前线程
NSThread *current = [NSThread currentThread];


3. 线程优先级

3.1 NSQualityOfService主要有5个枚举值,优先级别从高到低排布:

1. NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操作,比如处理点击事件,绘制图像到屏幕上
2. NSQualityOfServiceUserInitiated:次高优先级,主要用于执行需要立即返回的任务
3. NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级
4. NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务
5. NSQualityOfServiceBackground:后台优先级,用于完全不紧急的任务

一般主线程和没有设置优先级的线程都是默认优先级。

3.2 线程的调度优先级 priority(优先级)

+ (double)threadPriority;
+ (BOOL)setThreadPriority:(double)p;
- (double)threadPriority;
- (BOOL)setThreadPriority:(double)p;

调度优先级的取值范围是0.0 - 1.0,默认0.5,值越大,优先级越高

4. 线程通知

通知相关的三种形式

//由当前线程派生出第一个其他线程时发送,一般一个线程只发送一次
NSString * const NSWillBecomeMultiThreadedNotification;
//这个通知目前没有实际意义,可以忽略
NSString * const NSDidBecomeSingleThreadedNotification;
//线程退出之前发送这个通知
NSString * const NSThreadWillExitNotification;

例子



- (void)viewdidload{
// 创建线程
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain) object:nil]; 
//设置线程优先级
self.thread.qualityOfService = NSQualityOfServiceDefault; 
//启动线程
[self.thread start]; 

}



- (void)threadMain {
 //给线程设置名字. 可以不设置
    [[NSThread currentThread] setName:@"myThread"]; 
   // 给线程添加runloop
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
    //给runloop添加数据源   
   [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 
      
      //④:检查isCancelled
    while (![[NSThread currentThread] isCancelled]) {          
    //⑤启动runloop
        [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];  
    }
}



参考: iOS多线程篇

二、iOS多线程对比

  1. NSThread

每个NSThread对象对应一个线程,真正最原始的线程。

1)优点:NSThread 轻量级最低,相对简单。

2)缺点:手动管理所有的线程活动,如生命周期、线程同步、睡眠等。

  1. NSOperation

自带线程管理的抽象类。

1)优点:自带线程周期管理,操作上可更注重自己逻辑。

2)缺点:面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。

  1. GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。

1)优点:最高效,避开并发陷阱。

2)缺点:基于C实现。

  1. 选择小结

1)简单而安全的选择NSOperation实现多线程即可。
2)处理大量并发数据,又追求性能效率的选择GCD。
3)NSThread本人选择基本上是在做些小测试上使用,当然也可以基于此造个轮子。

更多精彩内容请关注“IT实战联盟”哦~~~


IT实战联盟.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容