zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    el-select下拉框选项太多导致卡顿,使用下拉框分页来解决
    vue+elementui前端添加数字千位分割
    Failed to check/redeclare auto-delete queue(s)
    周末啦,做几道面试题放松放松吧!
    idea快捷键
    解决flink运行过程中报错Could not allocate enough slots within timeout of 300000 ms to run the job. Please make sure that the cluster has enough resources.
    用.net平台实现websocket server
    MQTT实战3
    Oracle 查看当前用户下库里所有的表、存储过程、触发器、视图
    idea从svn拉取项目不识别svn
  • 原文地址:https://www.cnblogs.com/huangzs/p/7450793.html
Copyright © 2011-2022 走看看