多线程(NSThread, NSOperationQueue, NSObject,GCD)上
2016-03-02 21:36
609 查看
概念 ##一.程序 进程 线程
程序:由源代码生成的可执行应用进程:一个正在运行的程序可以看做一个进程(拥有独立运行时需要的所有的资源)
线程:程序中独立运行的代码段
NOTICE:一个进程是有一或多个进程组成; 进程负责资源的调度和分配;线程是程序的真正执行单元,负责代码的执行
二.单线程 多线程
单线程程序:只有一个线程, 即主线程,代码顺序执行,容易出现代码阻塞(页面假死)
多线程程序:有多个线程, 线程见独立运行, 能有效的避免代码阻塞,并且提高程序的运行性能
NOTICE:在单线程程序中, 主线程负责执行程序的所有代码,这些代码只能顺序执行;在多线程程序中,子线程和主线程独立运行, 能够并发执行;*iOS中关于UI的添加和刷新必须在主线程中操作
多线程创建的四种方法
iOS实现多线程实现种类a.NSThread:使用NSThread方式创建子线程时, 一定要在子线程中执行的方法中添加自动释放池!系统只会在主线程中, 默认帮助我们添加自动释放池,否则会造成内存泄露
//Thread的创建方法:
1.对象创建方法, 使用NSThread创建一个子线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(objectThread:) object:self]; //对象创建方式需要手动的执行 [thread start];
几个常用的类方法
[NSThread isMainThread]//YES就是当前主线程, NO就是子线程 [NSThread currentThread]//获取当前的线程
2.类的创建方式, 不需要我们手动执行
[NSThread detachNewThreadSelector:@selector(thread2Action) toTarget:self withObject:nil];
b.NSObject
//使用NSObiect类中的方法开辟子线程
[self performSelectorInBackground:@selector(backgroundAction) withObject:nil];
// 在子线程中执行的方法
// *在下面方法中, 处理UI界面东西, 记得回主线程中
//1.NSThread, NSObject这两种技术需要加上字典释放池(无论在ARC还是MRC都需要加)
- (void)backgroundAction { @autoreleasepool { NSLog(@"---是在主线程中吗--%d", [NSThread isMainThread]); } }
c.NSOperationQueue
//*NSOperation是一个抽象类, 我们都是使用它的子类
//*NSOperation的子类其实就是一个任务, 自己本身没有开辟子线程的能力, 所以说该任务在主线程中执行就是在主线程; 在子线程执行就是在子线程
c.1 NSInvocationOperation
//创建方法 NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil]; //执行该任务 [invoOperation start]
c.2 NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ //里面写具体的操作 NSLog(@"这是一个BlockOperation"); }]; //执行这个任务 [blockOperation start];
c.3 NSOperationQueue :这是任务队列, 就是一个容器, 里面都是一个个任务, 可以是block任务, 也可以是invocation任务
1.NSOperationQueue才具有开辟子线程的能力,
2.用来管理里面的所有任务
3.相当于开辟了一个线程队列
NSOperationQueue *queue= [[NSOperationQueue alloc] init]; //创建一个任务 NSInvocationOperation *inv = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invAction) object:nil]; NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < 100; i++) { NSLog(@"BB"); } }]; NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i < 100; i++) { NSLog(@"CC"); } }]; //把3个任务添加到线程队列中,添加到队列之后, 系统机会自己开启执行任务 //queue.maxConcurrentOperationCount = 3;//设置最大并发数, 默认值为-1 //队列FIFO, 先进先出, 所以当我们设置最大并发数为1的时候, 会按照添加的顺序, 先把最早加入队列的完成之后, 再去执行后添加的任务 // 设置依赖关系 // 一定要在任务添加到队列之前设置依赖关系 //A addDependency: B意思就是: A依赖于B, A的执行, 依赖B的完成 // *添加以来的时候, 要避免循环依赖, 循环依赖会导致两个任务都不执行 [block1 addDependency:block2]; [queue addOperation:inv]; [queue addOperation:block1]; [queue addOperation:block2];
一些常用的属性
//查看添加到队列中的多有任务 queue.operations, 里面放的是添加到队列中的多有任务 // 常用的方法 [queue cancelAllOperations]; 只能取消尚未开始的任务
d. GCD
d.1 GCD中只有两种类型的队列(dispatch_queue_t)
//1.串行(任务一个个执行)
//1.1系统自带的, 系统自带的串行队列是主线列
//1.2自己创建(只要是GCD自己创建的队列, 在MRC下需要进行释放, dispatch_release(自己创建队列的名字);, ARC不用释放, 系统帮我们管理)
dispatch_queue_t createSerial = dispatch_queue_create("com.lanou3g.createSerial1", DISPATCH_QUEUE_SERIAL);
2.并行
2.1系统自带
( 第一个参数队列优先级, 选择默认的; 预留参数, 没有任何作用)
*子线程队列, 也就是说, 将来在该队中执行的任务, 都
4000
是在子线程中完成
dispatch_queue_t systemConcurrent = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.2自己创建
dispatch_queue_t createConcurrent = dispatch_queue_create("com.currenQueue", DISPATCH_QUEUE_CONCURRENT);```
d.2 向队列中添加任务, 在队列中执行这个任务—dispath-async()
dispatch_async(createSerial, ^{ for (int i = 0; i < 100; i++) { NSLog(@"AAA"); } NSLog(@"---%d", [NSThread isMainThread]); //放置耗时操作 });
d.3 延迟执行代码的函数—dispatch_after()
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //参数就是想推迟的 NSLog(@"---after:%d", [NSThread isMainThread]); });
d.4 只执行一次的函数(无论在哪一个线程都直走一次), 用于创建单例—dispatch_once()
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 只执行一次的代码 });
d.4 重复执行— dispatch_apply()
// 执行的次数 // 队列(使用子线程队列)--线程死锁 // block里面的参数 dispatch_apply(5, createConcurrent, ^(size_t t){ NSLog(@"卢英杰是一夜%luÅ次郎", t); });
d.5 GCD-分组
dispatch_group_t createGroup = dispatch_group_create(); dispatch_group_async(createGroup, createConcurrent, ^{ //想检测的任务1 NSLog(@"AAAA"); }); dispatch_group_async(createGroup, createConcurrent, ^{ NSLog(@"BBBB"); }); dispatch_group_async(createGroup, createConcurrent, ^{ NSLog(@"CCCC"); }); // 分组有这样一个特性:标记在组中的任务都完成之后, 可以通知下面的函数执行 dispatch_group_notify(createGroup, systemSerial, ^{ NSLog(@"主线程刷新UI---%d", [NSThread isMainThread]); });
d.6 —*调整线程之间的次序(线程同步)
// 障碍 dispatch_async(createConcurrent, ^{ for (int i = 0; i < 100; i++) { NSLog(@"AAAAA"); } }); dispatch_async(createConcurrent, ^{ for (int i = 0; i < 100; i++) { NSLog(@"BBBBB"); } }); //添加一个障碍 dispatch_barrier_async(createConcurrent, ^{ NSLog(@"我是分割线"); }); dispatch_async(createConcurrent, ^{ for (int i = 0; i < 100; i++) { NSLog(@"CCCCC"); } });
预告:页面假死, 线程之间通讯以及卖票的线程互斥
相关文章推荐
- 详解IOS中GCD的使用
- 详解iOS中多线程app开发的GCD队列的使用
- gcd
- OC多线程
- 多线程应该知道的那几件事 GCD NSThread NSOperation
- 多线程编程4 - GCD
- 多线程学习资源
- block && Grand Central Dispatch
- GCD使用指南
- 关于GCD执行任务的理解
- iOS GCD编程
- IOS之多线程
- 2分钟学会GCD
- dispatch_group、dispatch_barrier、基于线程安全的多读单写
- Problem 1612 Hero's gcd
- 欧几里得算法的证明
- 使用GCD
- GCD学习 dispatch_barrier_async
- hdu1452因子和的积性函数
- hdu1852