zoukankan      html  css  js  c++  java
  • iOS开发多线程之NSThread

    一、NSThread的属性与方法

    1.NSThread 类方法

    类方法,顾名思义通过类名直接调用的方法

    1. + (void)detachNewThreadWithBlock:(void (^)(void))block   

    本方法适用于 ios(10.0),线程的创建,线程创建后直接运行,使用示例如下:

    [self detachNewThreadWithBlock:^{

    //想要实现的功能

    NSLog(@“currentThread:%@”,[NSThread currentThread]);

    }];

    2. + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

    本方法适用于 ios(10.0)之前版本,线程的创建,线程创建后直接运行,使用示例如下:

    [self detachNewThreadSelector:@Selector(用此线程执行的函数) toTarget:self withObject:@“想要传入的参数”];

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

    使用示例:NSThread *myMainThread=[NSThread mainThread];

    4. + (BOOL)isMainThread; // 判断当前线程是否是主线程

    使用示例:BOOL isMain=[NSThread isMainThread];

    5. + (BOOL)isMultiThreaded;//判断当前线程是否是多线程

    使用示例:BOOL isMulti=[NSThread isMultiThreaded];

    6. + (void)sleepUntilDate:(NSDate *)date;//当前线程休眠到指定日期

    使用示例:NSDate *myDate=[NSDate dateWithTimeInterval:5 sinceDate:[NSDate date]];

    [NSThread sleepUntilDate:myDate];

    7. + (void)sleepForTimeInterval:(NSTimeInterval)ti;//当前线程休眠指定时常

    使用示例:[NSThreadsleepForTimeInterval:5];

    8. + (void)exit;//强行退出当前线程

    使用示例:[NSThreadexit];

    9. + (double)threadPriority;//获取当前线程线程优先级

    使用示例:double dPriority=[NSThread threadPriority];

    10. + (BOOL)setThreadPriority:(double)p;//给当前线程设定优先级,调度优先级的取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高。

    使用示例:BOOL isSetting=[NSThread setThreadPriority:(0.0~1.0)];

    11. + (NSArray *)callStackReturnAddresses //线程的调用都会有函数的调用函数的调用就会有栈返回地址的记录,在这里返回的是函 数调用返回的虚拟地址,说白了就是在该线程中函数调用的虚拟地址的数组

    使用示例:NSArray* addressArray=[NSThread callStackReturnAddresses];

    12.+ (NSArray *)callStackSymbols //同上面的方法一样,只不过返回的是该线程调用函数的名字数字

    使用示例:NSArray* nameNumArray=[NSThread callStackSymbols];

    注意:callStackReturnAddress和callStackSymbols这两个函数可以同NSLog联合使用来跟踪线程的函数调用情况,是编程调试的重要手段

    2.NSthread 实例方法

    实例方法,顾名思义通过类对象实例调用的方法
    1. - (instancetype)initWithBlock:(void (^)(void))block 

    本方法适用于 ios(10.0),线程创建之后等待开始命令在开始运行,使用示例如下:

    NSThread *exampleThread=[NSThread alloc]initWithBlock:^{

    //想要实现的功能

    NSLog(@“currentThread:%@”,[NSThread currentThread]);

    }]

    [exampleThread start];

    2. - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument 

    本方法适用于 ios(10.0)之前版本,线程创建之后等待开始命令在开始运行,使用示例如下:

    NSThread *exampleThread = [[NSThread alloc] initWithTarget:self selector:@selector(用此线程执行的函数) object:@“想要传入的参数”];  

    [exampleThread start];

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

    使用示例:BOOL isMain=[exampleThreadisMainThread];

    4.- (void)setName:(NSString *)n;//设置线程名称

    使用示例:[exampleThread setName=@"叶阳"];

    5. - (void)cancel ;//取消线程

    使用示例:[exampleThread cancel];

    6. - (void)start ;//开始执行

    使用示例:[exampleThreadstart];

    7. - (void)main ;//线程的入口函数

    使用示例:[exampleThreadmain];

    8. -(void)isExecuting;//判断线程是否正在执行
    使用示例:BOOL isRunning=[exampleThread isExecuting];

    9. -(void)isFinished;//判断线程是否已经结束

    使用示例:BOOL isEnd=[exampleThread isFinished];

    10. -(void)isCancelled;//判断线程是否撤销

    使用示例:isCancel=[exampleThreadisCancelled];

    3.NSObject类的扩展

    1.- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)waitmodes:(nullable NSArray<NSString *> *)array;

    在主线程上执行函数,wait表示是否阻塞该方法,等待主线程空闲再运行,modes表示运行模式

    使用示例:[selfperformSelectorOnMainThread:@Selector(要运行的函数) withObject:@"想要传入的参数" waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array];

    2.- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

    本函数与上一个函数的kCFRunLoopCommonModes运行模式相同

    使用示例:[selfperformSelectorOnMainThread:@Selector(要运行的函数) withObject:@"想要传入的参数" waitUntilDone:(BOOL)wait];

    3.- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array 

    在指定线程上执行函数,wait表示是否阻塞该方法,等待指定线程空闲再运行,modes表示运行模式

    使用示例:[selfperformSelector:@Selector(要运行的函数) onThread:(自己指定的线程)withObject:@"想要传入的参数" waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array];

    4.- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait 

    本函数与上一个函数的kCFRunLoopCommonModes运行模式相同

    使用示例:[selfperformSelector:@Selector(要运行的函数) onThread:(自己指定的线程)withObject:@"想要传入的参数" waitUntilDone:(BOOL)wait];

    5.- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg

    本函数是隐式创建一个线程并执行

    使用示例: [self performSelectorInBackground:@Selector(要运行的函数) withObject:@"想要传入的参数"];


    4.NSthread的属性
    1.@property (readonly, retain) NSMutableDictionary *threadDictionary;//线程字典
    2.@property double threadPriority ; //优先级
    3.@property NSQualityOfService qualityOfService ; //线程优先级
    NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操作,比如处理点击事件,绘制图像到屏幕上
      NSQualityOfServiceUserInitiated:次高优先级,主要用于执行需要立即返回的任务
    NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级
      NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务
      NSQualityOfServiceBackground:后台优先级,用于完全不紧急的任务
    4.@property (nullable, copy) NSString *name;线程名称
    5.@property NSUInteger stackSize ;//线程使用栈区大小,默认是512K
    6.@property (readonly, getter=isExecuting) BOOL executing;//线程正在执行
    7.@property (readonly, getter=isFinished) BOOL finished;//线程执行结束
    8.@property (readonly, getter=isCancelled) BOOL cancelled;//线程是否可以取消

    5.NSThread有三个线程相关的通知

    NSWillBecomeMultiThreadedNotification:由当前线程派生出第一个其他线程时发送,一般一个线程只发送一次

    NSDidBecomeSingleThreadedNotification:这个通知目前没有实际意义,可以忽略

    NSThreadWillExitNotification线程退出之前发送这个通知


    二、线程锁

    线程锁的使用,主要是为了防止多个线程对同一个对象做操作,造成混乱和错误。
    NSLock / NSConditionLock / NSRecursiveLock /  @synchronized
        线程锁大都遵循NSLocking协议,这个协议提供了两个线程锁的基本函数
    - (void)lock;//加锁

    - (void)unlock;//解锁

    1.NSLock 

        - (BOOL)tryLock;//尝试加锁,成功返回YES ;失败返回NO ,但不会阻塞线程的运行

        - (BOOL)lockBeforeDate:(NSDate *)limit;

    //在指定的时间以前得到锁。YES:在指定时间之前获得了锁;NO:在指定时间之前没有获得锁。

         该线程将被阻塞,直到获得了锁,或者指定时间过期。

      - (void)setName:(NSString*)newName//为锁指定一个Name

      - (NSString*)name//返回锁指定的name

        @property (nullable, copy) NSString *name;线程锁名称 

    使用示例:

      NSLock* myLock=[[NSLock alloc]init];

    NSString *str=@"hello";

    [NSThread detachNewThreadWithBlock:^{
                [myLock lock];

    NSLog(@"%@",str);

    str=@"world";

                [myLock unlock];

        }];

    [NSThread detachNewThreadWithBlock:^{
                [myLock lock];

    NSLog(@"%@",str);

    str=@"变化了";

                [myLock unlock];

        }];


    输出结果不加锁之前,两个线程输出一样 hello;加锁之后,输出分辨为hello 与world。
    2.NSConditionLock

    使用此锁,在线程没有获得锁的情况下,阻塞,即暂停运行,典型用于生产者/消费者模型。
      - (instancetype)initWithCondition:(NSInteger)condition;//初始化条件锁

    - (void)lockWhenCondition:(NSInteger)condition;//加锁 (条件是:锁空闲,即没被占用;条件成立)

    - (BOOL)tryLock; //尝试加锁,成功返回TRUE,失败返回FALSE

    - (BOOL)tryLockWhenCondition:(NSInteger)condition;//在指定条件成立的情况下尝试加锁,成功返回TRUE,失败返回FALSE

    - (void)unlockWithCondition:(NSInteger)condition;//在指定的条件成立时,解锁

    - (BOOL)lockBeforeDate:(NSDate *)limit;//在指定时间前加锁,成功返回TRUE,失败返回FALSE,

    - (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;//条件成立的情况下,在指定时间前加锁,成功返回TRUE,失败返回FALSE,

    @property (readonly) NSInteger condition;//条件锁的条件

    @property (nullable, copy) NSString *name;//条件锁的名称

    使用示例:

      NSConditionLock* myCondition=[[NSConditionLock alloc]init];

        [NSThread detachNewThreadWithBlock:^{

            for(int i=0;i<5;i++)

            {

                [myCondition lock];

                NSLog(@"当前解锁条件:%d",i);

                sleep(2);

                [myCondition unlockWithCondition:i];

                BOOL isLocked=[myCondition tryLockWhenCondition:2];

                if(isLocked)

                {

                    NSLog(@"加锁成功!!!!!");

                    [myCondition unlock];

                }

            }

        }];

    输出结果,在条件2 解锁之后,等待条件2 的锁加锁成功。
    3. NSRecursiveLock

    此锁可以在同一线程中多次被使用,但要保证加锁与解锁使用平衡,多用于递归函数,防止死锁。
    - (BOOL)tryLock;//尝试加锁,成功返回TRUE,失败返回FALSE
    - (BOOL)lockBeforeDate:(NSDate *)limit;//在指定时间前尝试加锁,成功返回TRUE,失败返回FALSE
    @property (nullable, copy) NSString *name;//线程锁名称

    使用示例:
     

    -(void)initRecycle:(int)value

    {

        [myRecursive lock];

        if(value>0)

        {

            NSLog(@"当前的value值:%d",value);

            sleep(2);

            [self initRecycle:value-1];

        }

        [myRecursive unlock];

    }

    输出结果: 从你传入的数值一直到1,不会出现死锁
    4.@synchronized

    @synchronized指令做和其他互斥锁一样的工作(它防止不同的线程在同一时间获取同一个锁)

        @synchronized(线程共同使用的对象){

    多个线程使用同一个Obj,都会判断Obj是否已被占用,Obj空闲则用,繁忙则等待

        }

    使用示例:
    NSString *str=@"hello";
      for(int i=0;i<2;i++)

           {

      [NSThread detachNewThreadWithBlock:^{

    @synchronized (str) {

         NSLog(@"thread.name:%@------str:%@",str);

         str=@"world";

        }

    }];

      }

  • 相关阅读:
    又从头开始
    test1
    day1
    路飞学成-Python爬虫实战密训-第3章
    路飞学成-Python爬虫实战密训-第2章
    路飞学成-Python爬虫实战密训-第1章
    【软件测试】(homework3)覆盖问题
    【软件测试】(homework3)有关三角形的测试练习
    【软件测试】(homework2)错误分析
    【软件测试】(homework1)描述曾遇到且已经被解决的error
  • 原文地址:https://www.cnblogs.com/hecanlin/p/10725119.html
Copyright © 2011-2022 走看看