美文网首页
iOS 多线程(二)-NSThread

iOS 多线程(二)-NSThread

作者: 搬砖的crystal | 来源:发表于2021-05-28 21:29 被阅读0次

    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;
    

    callStackReturnAddresscallStackSymbols这两个函数可以同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}
    

    相关文章

      网友评论

          本文标题:iOS 多线程(二)-NSThread

          本文链接:https://www.haomeiwen.com/subject/hosssltx.html