多线程使用
-
讲NSthread目的就是说明白线程的生命周期,后面的GCD和更高级的NSOperation的生命周期都是自动管理的了。
(一)PThread(user/include跨平台的可以百科百度搜索):
导入<pthread.h>,pthread_create四参数:1.线程,2.线程相关NULL,3.方法,4.方法参数。
demo:
// pthread 演练
// pthread 演练 - (void)pthreadDemo { /** 几乎所有跨平台的框架都可以访问一个网站:baike.baidu.com 返回值 若线程创建成功,则返回0。若线程创建失败,则返回出错编号 - 非零即真,但是很多 C 语言的框架,成功是0,失败是编号 - 因为成功只有一个,失败有很多原因 参数 第一个参数:为指向线程标识符的指针 C 语言中,没有对象,是通过结构体来实现的,不需要使用 * 如果使用 C 语言的框架,定义类型,通常是 _t 或者 Ref 结尾 第二个参数:用来设置线程属性 第三个参数:是线程运行函数的起始地址 函数名就是指向函数在内存中的地址 类似的一个概念:数组名是指向数组第一个元素的地址 最后一个参数:是运行函数的参数 在 C 语言中 void *(指向任何地址的指针) 和 OC 中的 id(万能指针) 是等价的 格式 void * (*) (void *) 返回值 (*函数指针) (参数) ====== `桥接` __bridge - 是 ARC 开发时,用于 OC 对象和 C 语言对象转换时的标记 - ARC 开发的时候,编译器会根据代码结构,自动添加 retain/release/autorelease - ARC 不负责 C 语言的内存管理,如果碰到 C 语言的框架,如果出现 retain/new/copy/create... 程序员需要自己 release - 在 OC 对象和 C 语言的指针进行转换时,需要使用 __bridge,表示什么特殊处理都不做 - 后续课程会涉及桥接的所有权转换 - 标记的作用就是告诉编译器如何处理内存 > 提问:MRC 开发,需要 __bridge?因为 MRC 中所有的都是程序员来负责的! > 提示:__bridge可以利用 Xcode 智能提示 */ // 创建一个线程,执行指定的方法 // 线程代号 pthread_t threadId = NULL; id str = @"hello"; int result = pthread_create(&threadId, NULL, demo, (__bridge void *)(str)); if (result == 0) { NSLog(@"OK"); } else { NSLog(@"error"); } } // 由线程执行的函数 void * demo(void * param) { NSString *str = (__bridge NSString *)(param); // [NSThread currentThread]适用于所有多线程技术 NSLog(@"%@ - %@", [NSThread currentThread], str); return NULL; }
(二)NSThread:是OC的。创建有三种方法:
(1)对象方法: alloc initwithTarget
(2)类方法: detatchNewThreadSelector
(3)NSObject分类方法:performSlelctorInBackground:意味着任意OC对象都可以调用
-
在使用exit时候,要考虑是否有C语言框架资源,这种资源需要手动释放。
-
exit会取消当前线程。所以不要在主线程exit。
-
-
取消线程的方法:
-
内部:exit
-
外部:cancel,设置线程状态为取消,然后从内部判断(在关键节点位置增加判断,否则不会终止,需要判断)。is.canceled ->然后执行。
-
线程属性:
-
name:调用堆栈调试时候可以知道线程名称。用于排错。
-
stackSize:线程开多大。目前主线程子线程都是512K。可以修改。最小16K,必须是4K的整数倍。
-
3.threadPriority 0-1,0最高,默认0.5.优先级高只是CPU调度频率高,不是说先调用。一般不修改。
-
多线程资源抢夺:进程和进程之间内存是受保护的。但是一个进程的不同线程资源是共享的。在一起的。用到互斥锁。应该让锁定范围尽量小。越大越慢,锁的是{}里面的代码。要锁住共享资源的读和写部分。而且原子锁的self可以是任意OC对象,但是锁一定要全局。
-
原子属性和非原子属性:
-
原子属性:atomic。线程安全的。单写多读,同一时间只有一个线程可以写入,但是读取可以多读,可能会出现脏数据。。可能会出现脏数据。你我读都是15,但是写是安全的,读可能是错误的。但是原子属性性能比互斥锁性能高。atomic的锁叫自旋锁。
-
非原子属性:nonatomic。线程不安全。
-
原子属性锁效率比互斥锁高很多。只要用锁就有性能消耗。
-
最好不用锁。属性都用nonatomic,几乎所有的UIKit都是线程不安全的,所有的UI更新都在主线程。为了性能。