美文网首页
iOS开发多线程--NSThread

iOS开发多线程--NSThread

作者: 哦累哇滚筒洗衣机 | 来源:发表于2018-05-15 16:36 被阅读0次

    在日常开发中,能用到的多线程知识点有NSThreadNSOperationQueueGCD。至于Pthreads,因为基本用不到,就忽略不计了。

    多线程基本知识

    进程: 一个具有一定独立功能的程序关于某个数据集合的一次运行活动。可以理解成一个运行中的应用程序。
    线程: 程序执行流的最小单元,线程是进程中的一个实体。
    同步: 只能在当前线程按先后顺序依次执行,不开启新线程。
    异步: 可以在当前线程开启多个新线程执行,可不按顺序执行。
    队列: 装载线程任务的队形结构。
    并发: 线程执行可以同时一起进行执行。
    串行: 线程执行只能依次逐一先后有序的执行。

    具体组合如下

    同步执行 异步执行
    串行队列 当前线程,一个一个执行 其他线程,一个一个执行
    并行队列 当前线程,一个一个执行 开很多线程,一起执行

    多线程比较

    NSThread

    先看一下NSThread的相关属性方法

    @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 *)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 *)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
    

    以上有两个带有selector创建线程的方法,selector和target是有对应关系的,应该是target的selector方法,不能一贯的写self

    创建线程示例

    ViewController.m

    #import "ViewController.h"
    #import "Person.h"
    
    @interface ViewController ()
    
    @property (nonatomic, strong) Person *person;
    
    @end
    
    @implementation ViewController
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.person = [[Person alloc]init];
            self.person = [[Person alloc]init];
        [NSThread detachNewThreadSelector:@selector(sayHello:) toTarget:self.person withObject:@"Jim"];
        // 崩溃,self没有sayHello()方法
    //    [NSThread detachNewThreadSelector:@selector(sayHello:) toTarget:self withObject:@"Jim"];
        
        NSThread *thread = [[NSThread alloc]initWithTarget:self.person selector:@selector(sayHello:) object:@"Sam"];
        // 崩溃,self没有sayHello()方法
    //    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(sayHello:) object:@"Sam"];
        [thread start];
    
    }
    @end
    

    Person类

    //Person.h
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    - (void)sayHello:(NSString *)name;
    
    @end
    
    //Person.m
    #import "Person.h"
    
    @implementation Person
    
    - (void)sayHello:(NSString *)name{
        NSLog(@"Hello, %@", name);
        NSLog(@"hello %@",[NSThread currentThread]);
    }
    
    @end
    
    用NSThread下载图片阻塞示例:
    //为开辟线程按钮事件
    - (IBAction)blockTest:(id)sender {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Hint" message:@"Just For Test" delegate:nil cancelButtonTitle:@"YES" otherButtonTitles: nil];
        [alert show];
    }
    
    //开辟新线程按钮时间
    - (IBAction)noMultiAction:(id)sender {
        [self loadImage];
    }
    
    -(void)loadImage{
        NSURL *imageUrl = [NSURL URLWithString:kImageUrl];
        NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
        [self updateImageData:imageData];
    }
    -(void)updateImageData:(NSData*)imageData{
        UIImage *image = [UIImage imageWithData:imageData];
        [self performSelectorOnMainThread:@selector(updateImageOnMainThread:) withObject:image waitUntilDone:NO]; //更新UI的部分应该在主线程
    }
    
    - (void)updateImageOnMainThread:(UIImage *)image{
        self.showImageView.image = image;
    }
    
    - (IBAction)multiAction:(id)sender {
        [NSThread detachNewThreadSelector:@selector(loadImage) toTarget:self withObject:nil];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    

    点击左侧按钮效果如下:


    QQ20180515-162631-HD.gif

    点击右侧按钮效果如下:


    QQ20180515-162739-HD.gif

    用多线程果然能解决线程阻塞的问题,并且NSThread也比Pthreads好用,只不过实际开发中也许只有[NSThread currentThread];用的最多了。所以仅仅NSThread是不能满足我们的需要的。那就需要另外的手段了,比如GCD

    相关文章

      网友评论

          本文标题:iOS开发多线程--NSThread

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