您的位置:首页 > 其它

GCD使用与技巧(续)

2016-03-09 17:56 211 查看

后台执行 , 前台执行

// 前台执行
dispatch_async(dispatch_get_main_queue(), ^{
// do something
});
// 后台执行
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// do something
});


dispatch_once_t必须是全局或static变量 毕竟非全局或非static的dispatch_once_t变量在使用时会导致非常不好排查的bug

// 一次执行, 只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 单例
});


dispatch_queue_create,创建队列用的,它的参数只有两个, 而dispatch_queue_attr_t类型是有已经定义好的常量

// 串行
dispatch_queue_t queueSerial     = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
// 并行
dispatch_queue_t queueComcurrent = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);


dispatch_after

// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("myQueueSerial", DISPATCH_QUEUE_SERIAL);
// 打印第一条数据
NSLog(@"begin add block join in ...");
// 提交一个block
// 异步执行
dispatch_async(queue, ^{
// sleep 10s
[NSThread sleepForTimeInterval:10];
NSLog(@"sleep block done .... ");
});
// 5s 以后调教block
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"after block done ...");
});


结果输出
2016-03-09 16:51:32.382 PopView[3310:237164] begin add block join in ...
2016-03-09 16:51:37.383 PopView[3310:237164] after block done ...
2016-03-09 16:51:42.383 PopView[3310:237293] sleep block done ....


dispatch_time_t正确创建姿势

用dispatch_after的时候就会用到dispatch_time_t变量, 如何创建合适的时间

/**

* @param when 第一个参数一般是 DISPATCH_TIME_NOW,表示从现在开始

* @param delta delta 纳秒

*/

* 延时一秒可以这样

* dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);

* dispatch_time(DISPATCH_TIME_NOW, 1000 * USEC_PER_SEC);

* dispatch_time(DISPATCH_TIME_NOW, USEC_PER_SEC * NSEC_PER_USEC); — 每秒的毫秒数乘以每毫秒的纳秒数

//原型
dispatch_time_t dispatch_time ( dispatch_time_t when, int64_t delta );


dispatch_suspend, dispatch_resume: 提供挂起、恢复”队列的功能

dispatch_queue_t queueTest = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL);
//提交第一个block,延时5秒打印。
dispatch_async(queueTest, ^{
[NSThread sleepForTimeInterval:5];
NSLog(@"After 5 seconds...");
});
//提交第二个block,也是延时5秒打印
dispatch_async(queueTest, ^{
[NSThread sleepForTimeInterval:5];
NSLog(@"After 5 seconds again...");
});
//延时一秒
NSLog(@"sleep 1 second...");
[NSThread sleepForTimeInterval:1];
//挂起队列
NSLog(@"suspend...");
dispatch_suspend(queueTest);
//延时10秒
[NSThread sleepForTimeInterval:10];
NSLog(@"sleep 10 second...");
//恢复队列
dispatch_resume(queueTest);
NSLog(@"resume...");


2016-03-09 17:11:19.401 PopView[3430:251221] sleep 1 second...
2016-03-09 17:11:20.402 PopView[3430:251221] suspend...
2016-03-09 17:11:24.405 PopView[3430:251253] After 5 seconds...
2016-03-09 17:11:30.404 PopView[3430:251221] sleep 10 second...
2016-03-09 17:11:30.404 PopView[3430:251221] resume...
2016-03-09 17:11:35.409 PopView[3430:251253] After 5 seconds again...


dispatch_apply

dispatch_queue_t queue = dispatch_queue_create("queue-", DISPATCH_QUEUE_SERIAL);
// 执行5次
dispatch_apply(3, queue, ^(size_t i) {
NSLog(@"apply loop: %zu", i);
});
NSLog(@"after apply");


//    明明是异步, 却最后打印如下, dispatch_apply将外面的线程(main线程)“阻塞”了!
//    2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 0
//    2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 1
//    2016-03-09 17:19:32.628 PopView[3474:255956] apply loop: 2
//    2016-03-09 17:19:32.628 PopView[3474:255956] after apply


出现死锁的情况

// 情况一
- (void)updateUI1 {
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Update ui 1");

//死锁!
[self updateUI2];
});
}
- (void)updateUI2 {
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Update ui 2");
});
}


dispatch_queue_t queue11 = dispatch_queue_create("test.gcd", DISPATCH_QUEUE_SERIAL);
dispatch_apply(3, queue, ^(size_t i) {
NSLog(@"apply loop: %zu", i);

//再来一个dispatch_apply!死锁!
dispatch_apply(3, queue, ^(size_t j) {
NSLog(@"apply loop inside %zu", j);
});
});  // 这端代码只会输出“apply loop: 1”。。。就没有然后了 O.o --- 避免dispatch_apply的嵌套调用


dispatch_group_t

dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
// Do your something
});
// 当你无法直接使用队列变量时,就无法使用dispatch_group_async了,下面以使用AFNetworking时的情况:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//Enter group
dispatch_group_enter(group);
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//Deal with result...
//Leave group
dispatch_group_leave(group);
}    failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Deal with error...
//Leave group
dispatch_group_leave(group);
}];
//More request...  // 使用dispatch_group_enter,dispatch_group_leave就可以很方便处理


文章参照 : http://www.cocoachina.com/ios/20150505/11751.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: