ios线程第二发: NSThread(附录1)

NSThread:

1.创建、启动线程

1>手动启动的线程(经常使用)

// 线程一启动,就会在线程thread中执行self的run方法

NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil] start]

 2>创建线程后自动启动线程

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

3>隐式创建并启动线程

[self performSelectorInBackground:@selector(run) withObject:nil]

以上两种创建方法优缺点:创建快速简单,但是不能进行详细设置


(1)常用属性:

start:(将线程对象加入可调度线程池等待CPU调度)

线程的名字:name(可以自己设置)在商业级应用程序中,通常希望程序崩溃的时候,能够知道准确执行的线程!更容易排错

线程优先级:threadPriority默认0.5 取值范围是0.0—1.0  优先级高的调度频率比较高,不要进行修改优先级操作, 修改优先级有一个隐患->优先级翻转

线程的优先级:优先级高的任务只是表示 CPU 调度的频率高!

 误区:优先级高的任务会先执行完!


状态属性(只读):

             isExecuting 是否在执行

             isFinished 是否完成

             isCancelled 是否取消

线程大小:stackSize(默认线程都占用512kb,以前主线程1m, 子线程512k)

             可以自己设置,设置的时候是4k 得倍数

取消线程: cancle 可以在外部终止线程序执行,在执行方法中需要增加 isCancelled 判断,如果isCancelled == YES 直接返回


主线程相关用法

// 获得当前线程,开发中常用于调试,适用于所有线程技术number==1 表示主线程,其它为后台线程

+ (NSThread *)currentThread;

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

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

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

+isMultiThreaded / / 是否为多线程


2.线程的状态

1>新建:实例化线程对象

2>就绪

   (1)向线程发送 start 消息,线程对象被加入”可调度线程池”等待 cpu 调度

   (2)detach 和 performSelectorInBackground 方法会直接实例化一个线程池对象并加入”可调度线程池”

3>运行

    (1)cpu 负责调度”可调度线程池”中线程的执行

    (2)线程执行完成之前,状态可能会在就绪和运行之间来回切换

    (3)就绪和运行之间的状态变化由 cpu 负责,程序员不能干预

4>阻塞

    (1)当满足某个预定条件时,可以使用休眠或者阻塞线程的执行: sleepFormTimeInterval,sleepUntilDate,@synchronized(self)

    (2)线程对象进入阻塞状态后,会被从”可调度线程池”中移除, cpu 不再调度

   

5>死亡

    (1)死亡方式: 正常死亡 —> 线程执行完毕

                      非正常死亡 —> 线程内死亡: [NSThread exit] 强制终止,后续代码不会执行

                                            线程外死亡:[NSThread acncell] 通知线程对象取消(在执行方法中需要增加 isCancelled 判断,如果 isCancell == YES ,直接返回)

     (2)死亡后线程对象的 isFinish 属性为 YES

     (3)如果发送cancell 消息,线程对象的 isCancell 属性为 YES

     (4)死亡后 stackSize == 0 ,内存空间被释放

 注意:一旦线程被强行终止了,后续所有代码都不会再继续执行!

        没有给线程机会释放执行过程中申请的资源

        exit 方法会直接终止线程,要调用之前,需要考虑释放对象

        ARC 中通常不用考虑,如果涉及到 c 语言混编,如果分配了 c 语言的对象,在 exit 之前,一定记住 release!           

                        

3.多线程的安全隐患解决 —— 互斥锁:

   1>安全隐患:(当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题)

   2>互斥锁/同步锁:

     (保证同一时间内,只有一条线程执行)(synchronized)

   

    3>互斥锁使用格式:

     @synchronized(锁对象) { // 需要锁定的代码  }

   注意:

       互斥锁会降低性能,

       互斥锁锁定代码的范围,应该尽量的小

        使用互斥锁会影响并发的目的

       xcode 没有智能提示,因为互斥锁性能不好,苹果不建议使用

       synchronized(self) self 是一个能够加锁的 NSObject 对象,而且要保证所有线程都能共同访问到该对象

        一般情况而言, self 最方便使用加锁对象,如果程序只有一个地方涉及到加锁,绝大多数可以考虑使用 self

    

    4>原子属性(atomic)

        (1)能够实现”单写多读”的数据保护:

            同一时间只允许一个线程修改属性值,但是允许多个线程读取

            多线程读取数据的时候有可能出现脏数据, — 读取的数据可能会不正确

        (2)原子属性是默认属性,如果不考虑线程安全,要指定 

        (3)原子属性:nonatomic 和非原子属性: atomic

         原子属性 —> 默认属性: atomic

         原子属性是能够保证”线程安全”的属性,原子属性内部也有一把锁”自旋锁"

         自旋锁 和 synchronized

          A. 共同点:保证同一时间只有一个线程执行锁定范围内的代码

          B. 不同:  

          互斥锁: 当发现要执行的代码被其他线程锁定之后,线程会进入休眠状态,等待解锁之后,线程会被再次唤醒.

          自旋锁: 当发现要执行的代码被其他线程锁定之后,会以死循环的方式,监听是否解锁,一旦解锁,立即执行,执行性能高,适合于锁定非常短的代码

 

       5>线程安全:

          就是在多个线程同时对一个资源进行读写操作时,同样能够保证结果是正确的.

          要实现线程安全,必须要使用锁

          只要使用锁,就会降低性能

          

          UI 线程——主线程

          主线程又被称为 UI 线程,UIKIt 中几乎所有的控件都不是线程安全的,因此需要在主线程上更新 UI.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值