美文网首页
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