GCD 例子
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"%@", [NSThread currentThread]);
//[self gcdSyncDemo];
[self gcdDemo4];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touch me");
}
#pragma mark - GCD方法
#pragma mark 同步任务的阻塞
- (void)gcdSyncDemo
{
dispatch_queue_t q = dispatch_queue_create("cn.it.gcddemo", DISPATCH_QUEUE_SERIAL);
// 任务嵌套
dispatch_sync(q, ^{
NSLog(@"sync %@", [NSThread currentThread]);
// 耗时的任务,同步里面包含同步,会造成阻塞
// dispatch_sync(q, ^{
// 永远也不会执行到
// NSLog(@"async %@", [NSThread currentThread]);
// });
});
}
#pragma mark - 主(线程)队列,保证操作在主线程上执行
- (void)gcdDemo4
{
// 每一个应用程序都只有一个主线程
// 为什么需要在主线程上工作呢?
// 在iOS开发中,所有UI的更新工作,都必须在主线程上执行!
dispatch_queue_t q = dispatch_get_main_queue();
// 主线程是由工作的,而且除非将程序杀掉,否则主线程的工作永远不会结束!
// 阻塞了!!!
dispatch_sync(q, ^{
NSLog(@"come here baby!");
});
// 异步任务,在主线程上运行,同时是保持队形的
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ - %d", [NSThread currentThread], i);
});
}
}
#pragma mark - 全局队列(苹果为了方便多线程的设计,提供一个全局队列,供所有的APP共同使用)
- (void)gcdDemo3
{
// 全局队列与并行队列的区别
// 1> 不需要创建,直接GET就能用
// 2> 两个队列的执行效果相同
// 3> 全局队列没有名称,调试时,无法确认准确队列
// 记住:在开发中永远用DISPATCH_QUEUE_PRIORITY_DEFAULT
// 多线程的优先级反转!低优先级的线程阻塞了高优先级的线程!
dispatch_queue_t q =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
for (int i = 0; i < 10; ++i) {
// 异步任务,并发执行,但是如果在穿行队列中,仍然会依次顺序执行
dispatch_async(q, ^{
// [NSThread currentThread] 可以在开发中,跟踪当前线程
// num = 1,表示主线程
// num = 2,表示第2个子线程。。。
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
}
#pragma mark - 串行(一个接一个,排队跑步,保持队形)队列
- (void)gcdDemo1
{
// 将操作放在队列中
// 在C语言函数中,定义类型,绝大多数的结尾是_t或者ref
// 使用串行队列,的异步任务非常非常非常有用!新建子线程是有开销的,不能无休止新建线程
// 即可以保证效率(新建一个子线程),用能够实现并发
// 应用案例:
// 1> 从网络上上下载图片
// 2> 滤镜(高光,红眼...)
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
// 非ARC开发时,千万别忘记release
// dispatch_release(q);
// 串行行队列的同步任务,同样会在主线程上运行
// 提示:在开发中极少用d
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
for (int i = 0; i < 10; ++i) {
// 异步任务,并发执行,但是如果在串行队列中,仍然会依次顺序执行
dispatch_async(q, ^{
// [NSThread currentThread] 可以在开发中,跟踪当前线程
// num = 1,表示主线程
// num = 2,表示第2个子线程。。。
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
}
#pragma mark - 并行(并排跑,类似于赛跑)
- (void)gcdDemo2
{
// 特点:没有队形,执行顺序程序员不能控制!
// 应用场景:并发执行任务,没有先后顺序关系
// 并行队列容易出错!并行队列不能控制新建线程的数量!
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcd2", DISPATCH_QUEUE_CONCURRENT);
// for (int i = 0; i < 10; ++i) {
// // 异步任务
// dispatch_async(q, ^{
// // [NSThread currentThread] 可以在开发中,跟踪当前线程
// // num = 1,表示主线程
// // num = 2,表示第2个子线程。。。
// NSLog(@"%@ %d", [NSThread currentThread], i);
// });
// }
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
}
@end
//例子2----NSOperationQueue
import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSOperationQueue *myQueue;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myQueue = [[NSOperationQueue alloc] init];
[self demoOp1];
}
- (void)demoOp:(id)obj
{
NSLog(@"%@ - %@", [NSThread currentThread], obj);
}
#pragma mark - NSOperation方法
#pragma mark 设置任务的执行顺序
- (void)demoOp3
{
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"修饰图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"保存图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新UI %@", [NSThread currentThread]);
}];
// 设定执行顺序, Dependency依赖,可能会开多个,但不会太多
// 依赖关系是可以跨队列的!
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// GCD是串行队列,异步任务,只会开一个线程
[self.myQueue addOperation:op1];
[self.myQueue addOperation:op2];
[self.myQueue addOperation:op3];
// 所有UI的更新需要在主线程上进行
[[NSOperationQueue mainQueue] addOperation:op4];
}
#pragma mark NSInvocationOP
- (void)demoOp2
{
// 需要定义一个方法,能够接收一个参数
// 是用起来不够灵活
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demoOp:) object:@"hello op"];
// [self.myQueue addOperation:op];
[[NSOperationQueue mainQueue] addOperation:op];
}
#pragma mark NSBlockOperation
- (void)demoOp1
{
// NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"%@", [NSThread currentThread]);
// }];
//
// 所有的自定义队列,都是在子线程中运行
// [self.myQueue addOperation:block];
// 新建线程是有开销的
// 在设定同时并发的最大线程数时,如果前一个线程工作完成,但是还没有销毁,会新建线程
// 应用场景:网络开发中,下载工作!(线程开销:CPU,MEM)电量!
// 如果是3G,开3个子线程
// 如果是WIFI,开6个子线程
for (int i = 0; i < 10; ++i) {
[self.myQueue addOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
// 在主线程中执行
// [[NSOperationQueue mainQueue] addOperationWithBlock:^{
// NSLog(@"%@", [NSThread currentThread]);
// }];
}
@end
// GCD 线程例2
#import "MViewController.h"
@interface MViewController ()
@end
@implementation MViewController
/**
GCD的任务
1> disptach_sync 没有创建线程的欲望,就在当前线程执行
最主要的目的,阻塞并行队列任务的执行,只有当前的同步任务执行完毕后,后续的任务才能够执行
应用场景:用户登录!
2> dispatch_async 有创建线程的欲望,但是创建多少条线程,取决与队列的类型
GCD的队列
1> 串行队列 类似于跑步,只有一条跑道,最多能够有两条
如果存在异步任务,就会在新线程中执行异步任务,而同步任务依旧在当前线程中执行
2> 并行队列 类似与赛跑,具体跑道的数量,由系统决定
*/
- (void)viewDidLoad
{
[super viewDidLoad];
[self demo];
}
- (void)demo
{
dispatch_queue_t q = dispatch_queue_create("demo", DISPATCH_QUEUE_CONCURRENT);
// 在新线程中工作
dispatch_async(q, ^{
// 2
NSLog(@"%@", [NSThread currentThread]);
__block BOOL userLogon = NO;
// 用户登录,用户输入用户名,密码之后,提交到服务器确认身份
// 应用场景1:用来阻塞必须要按照顺序执行的任务
dispatch_sync(q, ^{
// 2
NSLog(@"用户网络登陆 %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:3.0f];
userLogon = NO;
});
// 身份确认之前,不能做其他事情
dispatch_async(q, ^{
// 可能是3,也可能是2
// 3.0(对的) / 立马执行(不对的)
NSLog(@"后续处理 %@", [NSThread currentThread]);
if (userLogon) {
NSLog(@"welcome");
} else {
NSLog(@"why");
}
});
// 队列是先进先出FIFO的,队列中的任务都是串着的
});
}