IOS多线程二 NSThread简约而不简单

IOS多线程二NSThread简约而不简单

今天就来着手教大家在IOS中简单的实现多线程。IOS实现多线程的方式有几种,但是要说最容易上手的还是NSThread,在IOS实现多线程的几种方法中,在我看来其实没有明显的好坏之分,只有适合之说,看何种场景下适合使用何种方式。

NSThread相对来说更加轻量级,并且更加具体,没有那么抽象,一个线程就是一个类的对象。你可以给这个对象附上需要执行的内容,其实也就是一个方法,可以通过调用该类的相关方法,控制其启动、关闭、暂停等。好吧,这里就不多说了,下面着重看下NSThread这个类。

直接在Xcode中就可以进入到NSThread类的.h文件中。可以看到NSThread是一个NSObject类的子类,是IOS开发的一个重要子框架Foundation框架中的一个类。进入NSThread类的.h文件可以看到一些NSThread比较常见的方法和属性。如下所述:

1.NSThread的init方法。

- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullableid)argumentNS_AVAILABLE(10_5,2_0);

该方法主要是用一个目标对象的方法来创建一个多线程NSThread类。其中target参数传递目标对象,selector参数传递目标对象的一个方法,其实就是多线程需要执行的内容。argument可以传递一个临时参数到多线程执行的方法中。

2.Start方法

该方法是控制线程启动执行的方法。init方法创建的NSThread对象,只有调用该方法才能启动执行。

3.detachNewThreadSelector方法

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullableid)argument;

该方法与init方法类似,参数也是一样,区别就在于,init方法初始化好一个多线程对象之后,需要调用start方法启动执行,而该方法创建好后直接自己启动执行,不需要再调用start方法。并且也不会产生显示的对象,无法通过对象的方法来控制结束或者暂停执行线程。

4.类方法isMultiThreaded

+ (BOOL)isMultiThreaded;

判断当前代表执行是否在主线程中

5.类方法currentThread

+ (NSThread*)currentThread;

获取当前线程。

6.线程暂停方法

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

该方法可传递一个秒级别的参数ti,来暂停执行当前代码所在的线程ti秒。

7.退出线程方法

+ (void)exit;

该方法是真正可以让线程退出的方法,在某个线程中调用该方法,该线程就会直接退出,之后的代码就不会再执行,而且要特别指出,该方法如果直接在主线程中调用的话,连主线程都会被直接终止哦,主线程如果都被终止了,那等于整个程序就已经失去活力了,APP都会整个卡死。

8 cancle标志方法

- (void)cancelNS_AVAILABLE(10_5,2_0);

@property(readonly,getter=isCancelled)BOOLcancelledNS_AVAILABLE(10_5,2_0);

很多初学者以为cancel就是退出线程,其实不是,这里的cancel其实就是类中的一个BOOL型变量,用户调用了cancel方法,该BOOL型变量就变成了真,再调用isCancel就可以看到其值是YES还是NO,然后再根据该标志位做一些工作。所以对比一下退出线程还是要靠exit方法,或者直接在线程中判断调用return退出。

9 设置线程优先级

+ (BOOL)setThreadPriority:(double)p;

@propertydoublethreadPriorityNS_AVAILABLE(10_6,4_0);// To be deprecated; use qualityOfService below

通过以上方法可以查看和设置线程优先级,优先级高的线程会优先执行,这里不建议进行此类设置,会打乱系统之前的线程优先级安排。可能造成某些底等级的线程卡顿或者长时间得不到执行。

以上大致就是NSThread类已经类中相关的属性和方法的基本介绍。下面就讲3个具体使用NSThread实现多线程的例子。

1.启动一个线程

代码示例

- (void)viewDidLoad 

{

     [super viewDidLoad];//进入某个viewController时启动一个线程

     //使用已经写好的线程执行方法FunctionForNSThread初始化一个NSThread类对象

     NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

     //启动该线程类对象

     [nowTestThread start];

}

- (void)FunctionForNSThread

{

      if([NSThread isMainThread])//使用NSThread类方法isMainThread判断当前线程是否为主线程

      {//主线程输出信息

             NSLog(@"now is in MainThread");

      }

      else

      {//非主线程输出信息

             NSLog(@"now is not in MainThread");

      }

}

这里的输出结果为

2016-09-20 23:12:25.566 MultiThreadExample[622:15261] now is not in MainThread

说明我们已经启动了另外一个线程。

2.启动一个循环执行的线程。

- (void)viewDidLoad 

{

     [super viewDidLoad];//进入某个viewController时启动一个线程

     //使用已经写好的线程执行方法FunctionForNSThread初始化一个NSThread类对象

     NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

     //启动该线程类对象

     [nowTestThread start];

}

- (void)FunctionForNSThread

{

      intnowIndex =0;

      while(YES)//while循环执行

      {

           nowIndex++;

           [NSThread sleepForTimeInterval:1];//每次执行到这里让线程暂停1秒钟

           if([NSThread isMainThread])//使用NSThread类方法isMainThread判断当前线程是否为主线程

           {//主线程输出信息

                NSLog(@"%d now is in MainThread",nowIndex);

           }

          else

          {//非主线程输出信息

                  NSLog(@"%d now is not in MainThread",nowIndex);

           }

      }

}

该段代码输出结果如下:

2016-09-20 23:15:02.010 MultiThreadExample[634:16310] 1 now is not in MainThread

2016-09-20 23:15:03.016 MultiThreadExample[634:16310] 2 now is not in MainThread

2016-09-20 23:15:04.018 MultiThreadExample[634:16310] 3 now is not in MainThread

2016-09-20 23:15:05.021 MultiThreadExample[634:16310] 4 now is not in MainThread

2016-09-20 23:15:06.022 MultiThreadExample[634:16310] 5 now is not in MainThread

2016-09-20 23:15:07.023 MultiThreadExample[634:16310] 6 now is not in MainThread

2016-09-20 23:15:08.024 MultiThreadExample[634:16310] 7 now is not in MainThread

2016-09-20 23:15:09.025 MultiThreadExample[634:16310] 8 now is not in MainThread

2016-09-20 23:15:10.026 MultiThreadExample[634:16310] 9 now is not in MainThread

………

如果不强行终止程序,该线程会一直执行下去,数字编码也会从1开始一直不断增大。

还有一点我们在线程中使用[NSThreadsleepForTimeInterval:1];方法每次循环开始时让线程暂停1秒钟,大家一定要注意,在这种循环执行的线程中,一定要设置循环停止时间,否则线程不断死循环就会将设备CPU彻底占用,如果你运行的设备是双核CPU,你启动一个不设置循环停止时间的线程,就会直接将其中一个CPU全部沾满卡死。

从上述输出结果中也可以看到,每次输出间隔时间都是1秒钟。也就是说该循环执行的内容每隔1秒执行一次。

3.终止一个线程

停止一个线程有很多方法,初学者常犯的一个错误就是调用NSThread类的cancel方法。时机调用该方法并没有作用,该方法中设置的cancel只是一个标记位,调用cancel方法之后,再通过iscancel方法获取该标记位就可以得到是否已经cancel,真正的cancel需要在该线程的执行方法体中调用类方法exit来真正退出该线程。

- (void)viewDidLoad 

{

      [super viewDidLoad];//进入某个viewController时启动一个线程

      //使用已经写好的线程执行方法FunctionForNSThread初始化一个NSThread类对象

      NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

      //启动该线程类对象

      [nowTestThread start];

      [NSThread sleepForTimeInterval:10];//主线程暂停执行10秒钟,这里测试需要,一般不建议暂停主线程。

      [nowTestThread cancel];

}

- (void)FunctionForNSThread

{

      intnowIndex =0;

      while(YES)//while循环执行

      {

            nowIndex++;

            [NSThread sleepForTimeInterval:1];//每次执行到这里让线程暂停1秒钟

            if([NSThread isMainThread])//使用NSThread类方法isMainThread判断当前线程是否为主线程

            {//主线程输出信息

                 NSLog(@"%d now is in MainThread",nowIndex);

            }

            else

            {//非主线程输出信息

                 NSLog(@"%d now is not in MainThread",nowIndex);

            }

           if([[NSThread currentThread] isCancelled])//先通过currentThread方法获取当前线程,再通过isCancelled方法获取cancel标志位

           {

                 NSLog(@"退出线程之前");

                 [NSThread exit];//cancel标志位为真,说明线程外部已经发出了终止线程的标志信号,在本线程调用exit停止线程。

                 NSLog(@"退出线程之后");//该log永远不会被打印,因为在exit方法之后的代码都不会再执行

           }

      }

}

该段代码执行结果如下:

2016-09-20 23:28:37.258 MultiThreadExample[675:21235] 1 now is not in MainThread

2016-09-20 23:28:38.265 MultiThreadExample[675:21235] 2 now is not in MainThread

2016-09-20 23:28:39.267 MultiThreadExample[675:21235] 3 now is not in MainThread

2016-09-20 23:28:40.272 MultiThreadExample[675:21235] 4 now is not in MainThread

2016-09-20 23:28:41.277 MultiThreadExample[675:21235] 5 now is not in MainThread

2016-09-20 23:28:42.281 MultiThreadExample[675:21235] 6 now is not in MainThread

2016-09-20 23:28:43.283 MultiThreadExample[675:21235] 7 now is not in MainThread

2016-09-20 23:28:44.288 MultiThreadExample[675:21235] 8 now is not in MainThread

2016-09-20 23:28:45.294 MultiThreadExample[675:21235] 9 now is not in MainThread

2016-09-20 23:28:46.312 MultiThreadExample[675:21235] 10 now is not in MainThread

2016-09-20 23:28:46.312 MultiThreadExample[675:21235]退出线程之前

因为主线程在暂停10秒之后将之前启动的线程cancel标志置为YES,而在线程内部每次循环都会判断cancel标志位,如果为真就调用exit退出线程,而每次循环间隔为1秒,所以执行10次之后线程就退出了。

另外exit之后的代码都不会被执行,所以“退出线程之后”log没有打印。

以上就是IOS多线程实现方案之一 NSThread的相关内容,如果大家有什么心得或者不同见解可以找我沟通,QQ 1828141617   邮箱 yimaoruanjian@126.com

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

推荐阅读更多精彩内容

  • 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案...
    张战威ican阅读 603评论 0 0
  • 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案...
    伯恩的遗产阅读 274,410评论 251 2,332
  • 1、简介:1.1 iOS有三种多线程编程的技术,分别是:1.、NSThread2、Cocoa NSOperatio...
    LuckTime阅读 1,339评论 0 1
  • 一、前言 上一篇文章iOS多线程浅汇-原理篇中整理了一些有关多线程的基本概念。本篇博文介绍的是iOS中常用的几个多...
    nuclear阅读 2,047评论 6 18
  • 骏爷的天阅读 152评论 0 0