文章目录
程序APP进程、线程、多线程
1.程序是计算机(电脑,智能手机,机器人等有操作系统的智能新生物)指令的集合,以文件形式存储在磁盘上。
2.进程是一个正在运行的程序实例,是一个程序在其自身的地址空间中的一次执行活动。
3.进程由内核对象和地址空间组成。
4.线程由内核对象和线程栈组成,它是进程运行过程中的某个时间片,多核CUP时,线程就实现了同时运行。
iOS提供四种多线程编程技术
NSThread
NSThread相对其他几个比较轻量级。
需要自己管理线程的生命周期,线程同步。
线程同步对数据的加锁会有一定的系统开销。
Cocoa NSOperation
是对GCD的封装,不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作任务上。可以轻松调用cancelOperation取消操作任务。
相关类NSOperation,NSOperationQueue。
NSOperation是个抽象类,使用它必须用它的子类,可以自定义子类或用Cocoa定义好的两个子类NSInvocationOperation, NSBlockOperation.
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。
pthread
pthread是一套通用的多线程API,适用于Linux、windows、Unix跨平台,可移植,使用C语言,生命周期需要程序员管理,iOS开发中使用很少。
GCD
Grand Central Dispatch是iOS4.0开始后,Apple开发的一个多核编程的解决方案。
GCD确实好用,很强大,是替代其他多线程编程很高效强大的技术。相比NSOperation,GCD无法轻松取消任务(可以取消)。用不好可能出现线程死锁。如
- (void)viewDidLoad{
[super viewDidLoad];
NSLog(@"=================4");
dispatch_sync(dispatch_get_main_queue(),^{
NSLog(@"=================5");
});
NSLog(@"=================6");
}
应改为
- (void)viewDidLoad{
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"=================1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"=================2");
});
NSLog(@"=================3");
});
}
GCD多线程的管理
- 开不开线程,取决于执行任务的函数,同步不开,异步才能开
- 开几条线程,取决于队列,串行开一条,并发可以开多条(异步)
串行队列Serial Dispatch Queue
队列中的任务只会顺序执行,主队列是系统自带的串行队列。
要避免多线程更新相同资源导致数据竞争时,用串行队列.
dispatch_queue_t q = dispatch_queue_create("nameOfQueue",dispatch_queue_serial);
并行队列Concurrent Dispatch Queue
队列中的任务通常会并发执行,全局队列是系统提供的并行队列。
dispatch_queue_t q = dispatch_queue_create("nameOfQueue",dispatch_queue_concurrent);
全局队列
是系统提供的,直接拿过来用就可以;与并行队列类似,但是调试时,无法确认操作所在队列。
dispatch_queue_t q = dispatch_global_queue_create(DISPATCH_QUEUE_PRIORITY_DAFAULT,0);
主队列
每一个应用开发程序对应唯一一个主队列,直接get即可,在多线程开发中,使用主队列更新UI。
dispatch_queue_t q = dispatch_get_main_queue(DISPATCH_QUEUE_PRIORITY_DAFAULT,0);
等待GCD任务
GCD实现1,2并行和3串行和4,5串行,4,5是并行。3延时3秒执行。
- (void)mutiThreadWork{
//并行执行1,2
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSLog(@"1");
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2");
});
//1,2处理晚后,延时执行3
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC);
dispatch_after(time , dispatch_get_global_queue(0, 0), ^{
NSLog(@"3");
//4,5串行
dispatch_async(group, dispatch_get_main_queue(), ^{
sleep(10);
NSLog(@"4");
});
dispatch_async(group, dispatch_get_main_queue(), ^{
sleep(5);
NSLog(@"5");
});
});
});
}
详细参阅:
GCD实现异步线程的等待实行
取消GCD任务
请参阅:
https://www.cnblogs.com/beckwang0912/p/7136862.html
GCD实现信号量管理
请参阅:
http://blog.csdn.net/huifeidexin_1/article/details/9494975
http://blog.csdn.net/yongyinmg/article/details/38065255
GCD死锁
请参阅:
iOS 开发微信公众号博文
总结一句话:除非串行队列(包含主队列)的外层有不同队列的异步线程,否则串行队列的同步线程造成死锁。
GCD使用应该注意的
- 串行队列开启异步任务,是有执行顺序的。
- 并行队列里开启同步任务是有执行顺序的,只有异步任务才没有顺序。
- 主队列是GCD自带的串行队列,会在主线程中顺序执行。全局队列开启异步任务,并发执行(顺序不定)。
- 在同一串行队列开启异步任务后嵌套同步任务(修改UI或其他)造成死锁。
- 更多内容请参阅《Objective-C高级编程——iOS与OS X多线程和内存管理》