• NSThread那些事儿


    NSThread

    哎呀,它面向对象,再去看看苹果提供的API,对比一下Pthreads,简单明了,人生仿佛又充满了阳光和希望,我们先来一看一下系统提供给我们的API自然就知道怎么用了,来来来,我给你注释一下啊:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    @interface NSThread : NSObject
    //当前线程
    @property (class, readonly, strong) NSThread *currentThread;
    //使用类方法创建线程执行任务
    + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
    + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
    //判断当前是否为多线程
    + (BOOL)isMultiThreaded;
    //指定线程的线程参数,例如设置当前线程的断言处理器。
    @property (readonly, retain) NSMutableDictionary *threadDictionary;
    //当前线程暂停到某个时间
    + (void)sleepUntilDate:(NSDate *)date;
    //当前线程暂停一段时间
    + (void)sleepForTimeInterval:(NSTimeInterval)ti;
    //退出当前线程
    + (void)exit;
    //当前线程优先级
    + (double)threadPriority;
    //设置当前线程优先级
    + (BOOL)setThreadPriority:(double)p;
    //指定线程对象优先级 0.0~1.0,默认值为0.5
    @property double threadPriority NS_AVAILABLE(10_6, 4_0);
    //服务质量
    @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0);
    //线程名称
    @property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
    //栈区大小
    @property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);
    //是否为主线程
    @property (class, readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);
    //获取主线程
    @property (class, readonly, strong) NSThread *mainThread NS_AVAILABLE(10_5, 2_0);
    //初始化
    - (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
    //实例方法初始化,需要再调用start方法
    - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
    - (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
    //线程状态,正在执行
    @property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0);
    //线程状态,正在完成
    @property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);
    //线程状态,已经取消
    @property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);
    //取消,仅仅改变线程状态,并不能像exist一样真正的终止线程
    - (void)cancel NS_AVAILABLE(10_5, 2_0);
    //开始
    - (void)start NS_AVAILABLE(10_5, 2_0);
    //线程需要执行的代码,一般写子类的时候会用到
    - (void)main NS_AVAILABLE(10_5, 2_0);
    @end
    另外,还有一个NSObject的分类,瞅一眼:
    @interface NSObject (NSThreadPerformAdditions)
    //隐式的创建并启动线程,并在指定的线程(主线程或子线程)上执行方法。
    - (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;
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<nsstring *> *)array NS_AVAILABLE(10_5, 2_0);
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
    - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);
    @end</nsstring *></nsstring *>

    上面的介绍您还满意吗?小的帮您下载一张图片,您瞧好:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    -(void)creatBigImageView{
        self.bigImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:_bigImageView];
        UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
        startButton.frame = CGRectMake(0, 0, self.view.frame.size.width / 2, 50);
        startButton.backgroundColor = [UIColor grayColor];
        [startButton setTitle:@"开始加载" forState:UIControlStateNormal];
        [startButton addTarget:self action:@selector(loadImage) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:startButton];
         
        UIButton *jamButton = [UIButton buttonWithType:UIButtonTypeSystem];
        jamButton.frame = CGRectMake(self.view.frame.size.width / 2, 0, self.view.frame.size.width / 2, 50);
        jamButton.backgroundColor = [UIColor grayColor];
        [jamButton setTitle:@"阻塞测试" forState:UIControlStateNormal];
        [jamButton addTarget:self action:@selector(jamTest) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:jamButton];
    }
    -(void)jamTest{
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"线程阻塞" message:@"" delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
        [alertView show];
    }
    -(void)loadImage{
        NSURL *imageUrl = [NSURL URLWithString:@"http://img5.duitang.com/uploads/item/201206/06/20120606174422_LZSeE.thumb.700_0.jpeg"];
        NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
        [self updateImageData:imageData];
    }
    -(void)updateImageData:(NSData*)imageData{
        UIImage *image = [UIImage imageWithData:imageData];
        self.bigImageView.image = image;
    }

    运行结果:

    我们可以清楚的看到,主线程阻塞了,用户不可以进行其他操作,你见过这样的应用吗?

    所以我们这样改一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    -(void)creatBigImageView{
        self.bigImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:_bigImageView];
        UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
        startButton.frame = CGRectMake(0, 20, self.view.frame.size.width / 2, 50);
        startButton.backgroundColor = [UIColor grayColor];
        [startButton setTitle:@"开始加载" forState:UIControlStateNormal];
        [startButton addTarget:self action:@selector(loadImageWithMultiThread) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:startButton];
         
        UIButton *jamButton = [UIButton buttonWithType:UIButtonTypeSystem];
        jamButton.frame = CGRectMake(self.view.frame.size.width / 2, 20, self.view.frame.size.width / 2, 50);
        jamButton.backgroundColor = [UIColor grayColor];
        [jamButton setTitle:@"阻塞测试" forState:UIControlStateNormal];
        [jamButton addTarget:self action:@selector(jamTest) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:jamButton];
    }
    -(void)jamTest{
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"阻塞测试" message:@"" delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
        [alertView show];
    }
    -(void)loadImageWithMultiThread{
        //方法1:使用对象方法
        //NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(loadImage) object:nil];
        //??启动一个线程并非就一定立即执行,而是处于就绪状态,当CUP调度时才真正执行
        //[thread start];
         
        //方法2:使用类方法
        [NSThread detachNewThreadSelector:@selector(loadImage) toTarget:self withObject:nil];
    }
    -(void)loadImage{
        NSURL *imageUrl = [NSURL URLWithString:@"http://img5.duitang.com/uploads/item/201206/06/20120606174422_LZSeE.thumb.700_0.jpeg"];
        NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
        //必须在主线程更新UI,Object:代表调用方法的参数,不过只能传递一个参数(如果有多个参数请使用对象进行封装),waitUntilDone:是否线程任务完成执行
        [self performSelectorOnMainThread:@selector(updateImageData:) withObject:imageData waitUntilDone:YES];
         
        //[self updateImageData:imageData];
    }
    -(void)updateImageData:(NSData*)imageData{
        UIImage *image = [UIImage imageWithData:imageData];
        self.bigImageView.image = image;
    }

    运行结果:

    哎呀,用多线程果然能解决线程阻塞的问题,并且NSThread也比Pthreads好用,仿佛你对精通熟练使用多线程又有了一丝丝曙光。假如我有很多不同类型的任务,每个任务之间还有联系和依赖,你是不是又懵逼了,上面的你是不是觉得又白看了,其实开发中我觉得NSThread用到最多的就是[NSThread currentThread];了。(不要慌,往下看... ...)

    4408163-7b841d1c77877c4c.jpg

    转自:http://www.cocoachina.com/ios/20170829/20404.html

  • 相关阅读:
    如何进入高效学习状态
    shell printf命令:格式化输出语句
    C# virtual、abstract
    git解决Could not execute editor
    go defer笔记
    git从其他分支提取文件merge到当前分支
    golang map
    状态模式
    golang单例模式
    go 单元测试时读取配置文件
  • 原文地址:https://www.cnblogs.com/huangzs/p/7450793.html
Copyright © 2020-2023  润新知