美文网首页
iOS-基础巩固-Pthread & NSThread

iOS-基础巩固-Pthread & NSThread

作者: Masson | 来源:发表于2018-01-24 16:09 被阅读0次

    进程

    进程是指在系统中正在运行的一个应用程序

    每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内

    线程

    一个进程要想执行任务,必须得有线程(每一个进程至少要有一条线程)

    一个进程(程序)的所有任务都在线程中执行

    多线程原理

    同一时间,CPU只能处理一条线程,只有一条线程在执行

    多线程并发(同时)执行,其实就是CPU快速的在多条线程之间调度(切换)

    如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象

    多线程优点

    能适当提高程序的执行效率

    能适当提高资源利用率(CPU、内存利用率)

    多线程的缺点

    创建线程是有开销的,iOS下主要成本包括:内核数据结构(大约 1 KB)、栈空间(子线程 512 KB、主线程 1 MB, 也可以使用 setStackSize: 设置,但必须是 4 K 的倍数,而且最小是 16 K),创建线程大约需要90毫秒的创建时间

    线程越多,CPU在调度线程上的开销就越大

    程序设计更加复杂: 比如线程之间的通信、多线程的数据共享

    如果开启大量的线程,会降低程序的性能:

    CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源
    
    每条线程被调度执行的频次会降低(线程的执行效率降低)
    
    移动开发中会导致设备发烫,耗电量加大
    

    主线程(UI线程)的主要作用

    显示/刷新 UI界面

    处理UI事件(比如点击事件、滚动事件、拖拽事件等)

    Pthread

    /*
    pthread_create(pthread_t  _Nullable *restrict _Nonnull,
                  const pthread_attr_t *restrict _Nullable,
                  void * _Nullable (* _Nonnull)(void * _Nullable),
                  void *restrict _Nullable)
    
    参数:
    1.线程代号的地址
    2.线程的属性
    3.调用函数的指针
    4.传递给函数的参数
    返回值:
    - 如果是 0, 表示正确
    - 如果是非0,表示错误码
    
    第三个参数说明:
    void *--(*)--(void *)
    返回值--(函数指针)--(参数)
    void *  相当于 OC中的id
    */
    #import <pthread.h> //POSIX 多线程开发框架
    
    - (void)pthreadDemo{
        pthread_t threadID;
        NSString * str = @"Hello Pthread";
    
        /*
        - 在 ARC 开发中, 如果遇到 OC和C 语言中相同数据类型进行转换,需要使用__bridge "桥接"
        - 在 MRC 开发中,不需要桥接
        - 在 OC 中,如果是ARC开发,编译器会在编译的时候,自动根据代码结构,添加 retain , release, autorelease
        - ARC 只负责 OC部分的代码,不负责C的代码. 如果C的代码里面出现了 retain/create/copy 字样的函数,都需要release
        */
        int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));
        if (result == 0) {
            for (int i  = 0; i < 20; i++) {
                NSLog(@"OK!");
            }
        }else{
            NSLog(@"error %d",result);
        }
    
    void * demo(void *param){
        NSString * sss = (__bridge NSString *)(param);
        NSLog(@"%@---%@",[NSThread currentThread],sss);
        return NULL;
    }
    
    

    NSThread

    创建方式:
    一个NSThread对象就代表一条线程
    线程一启动,就会在线程thread中执行self的run方法

    //创建线程
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"thread"];
    //启动线程
    [thread start];
    
    //二、创建线程后自动启动线程
    [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"Detach"];
    
    //三、隐式创建并启动线程,非常方便.不用NSThread对象
    //NSObject的分类 意味着所有的基础NSObject的都可以使用这个方法
    [self performSelectorInBackground:@selector(demo:) withObject:@"Background"];
    
    上述2种创建方式优缺点
    优点:简单快捷
    缺点:无法对线程进行更详细的设置
    

    线程状态

    // 启动线程,进入就绪状态
    - (void)start;
    
    //阻塞(暂停)线程,进入阻塞状态
    + (void)sleepUntilDate:(NSDate *)date;
    + (void)sleepForTimeInterval:(NSTimeInterval)ti;
    
    //强制停止线程 进入死亡状态
    //一旦强行终止线程,后续的所有代码都不会被执行
    //注意:在终止线程执行前,应该要释放之前分配的对象!!
    + (void)exit;
    //注意一旦线程停止(死亡)了,就不能再次开启任务
    

    线程属性

    NSThread * t = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
    //在大型的商业项目中,通常希望程序在崩溃的时候,能够获取到程序所在的线程!
    t.name = @"Thread A";
    //优先级 从 0.0 -- 1.0  默认值 0.5
    /**  优先级翻转
    优先级 只是保证 CPU 调度的可能性会高!
         
    多线程目的:将耗时操作放在后台,不阻塞UI线程!
    建议:在开发的时候,不要修改优先级
         
    在多线程开发中,不要相信一次的运行结果!!
    */
    t.threadPriority = 0.1;
    [t start];
    

    线程安全

    //nonatomic : 非原子属性,不会为setter方法加锁
    //atomic : 原子属性,为setter方法加锁(默认)单写多读的一种多线程技术
    
    //@synchronized
    //互斥锁 的范围 应该尽量小,范围大了 效率就差
    //参数:任意OC对象都OK!一般用self!全局对象
    //局部变量是每一个线程单独拥有的,因此没法加锁!!!
    
    /**
     实际上,原子属性内部有一个锁,自旋锁
     自旋锁 & 互斥锁
     - 共同点:
        都能够保证线程安全.
     - 不同点:
        互斥锁:如果线程被锁在外面,哥么就会进入休眠状态,等待锁打开,然后被唤醒!
        自旋锁:如果线程被锁在外面,哥么就会用死循环的方式,一直等待锁打开!
     
     无论什么锁,都很消耗新能.效率不高
     
     * 线程安全
        在多个线程进行读写操作时,保证数据正确!
     
     * UI 线程,共同约定:所有更新UI 的操作都放在主线程上执行!
     原因:UIKit框架都是线程不安全的!!(因为线程安全效率下降!)
     */
    
    NSData * data ;
    //原子属性 == YES 先把文件保存在一个临时的文件中,等全部写入之后,再改名
    [data writeToFile:@"hank.mp4" atomically:YES];
    

    线程间通讯

    //五种方法:
    - (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;
    // equivalent to the first method with kCFRunLoopCommonModes
    
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array ;
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
    // equivalent to the first method with kCFRunLoopCommonModes
    - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;
    

    相关文章

      网友评论

          本文标题:iOS-基础巩固-Pthread & NSThread

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