iOS多线程编程——GCD的使用

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。
GCD方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中。
GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。

GCD和block的配合使用,可以方便地进行多线程编程。


设计:GCD的工作原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
 
GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行
队列dispatch queue分为下面三种:
1、用户队列Serial:又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。用函数 dispatch_queue_create创建的队列。
2、全局队列Global queues:又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。

3、主线程队列Main dispatch queue:它是全局可用的serial queue,它是在应用程序主线程上执行任务的,且是串行的。可以调用dispatch_get_main_queue()来获得。

 1、队列
 (1)全局队列
 (1-1)主线程
dispatch_queue_t queue = dispatch_get_main_queue();
 (1-2)子线程 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
 (2)自定义队列
 (2-1)串行队列 dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_SERIAL);
 (2-2)并行队列 dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_CONCURRENT);
 2、任务
 (1)同步 dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
 (2)异步 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
 3、dispatch_once 只执行一次
 4、dispatch_after 延迟执行
 5、dispatch_group 任务组操作
 6、dispatch_barrier 分段操作
 自定义并行队列时,在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
 7、dispatch_semaphore 信号量


GCD是多线程的一种。

既有同步方法,也有异步方法,如下所示:

1)同步:同步执行-会阻塞进程,造成应用卡顿

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self showCount:@(1)];
});

2)异步:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self showCount:@(1)];
});

GCD的有多种方式,代码示例:

- (void)showCount:(NSNumber *)number
{
    NSInteger count = arc4random() % 10;
    count = 10;
    for (int i = 0; i < count; i++)
    {
        NSLog(@"第 %@ 个 i = %@", number, @(i));
        
        // 休眠n秒再执行
        [NSThread sleepForTimeInterval:0.2];
    }
}
- (void)downloadImage:(NSString *)imageUrl
{
    NSURL *url = [NSURL URLWithString:imageUrl];
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    UIImage *image = [[UIImage alloc] initWithData:data];
    if (image == nil)
    {
        
    }
    else
    {
        // 下载成功后 反回主线程处理
        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateImage:image];
        });
    }
}
- (void)updateImage:(UIImage *)image
{
    self.imageview.image = image;
}

// 同步执行-会阻塞进程,造成应用卡顿
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self showCount:@(1)];
});
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self showCount:@(2)];
});


// 子线程异步
- (void)runAsynchronizationGrobal
{
    NSLog(@"---start---");
    
    // 获取子队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 使用异步函数封装三个任务
    dispatch_async(queue, ^{
        NSLog(@"任务1---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.2]; // 模拟运行时间
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.2]; // 模拟运行时间
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    
    NSLog(@"---end---");
}


// 主线程同步(死锁)
- (void)runSynchronizationMain
{
    NSLog(@"---start---");
    
    // 获取主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 使用同步函数封装三个任务
    dispatch_sync(queue, ^{
        NSLog(@"任务1---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    dispatch_sync(queue, ^{
        NSLog(@"任务2---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    dispatch_sync(queue, ^{
        NSLog(@"任务3---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    
    NSLog(@"---end---");
}


// 主线程异步,在主线程中先顺序执行完当前任务,再顺序执行主线程中其他线程任务
- (void)runAsynchronizationMain
{
    NSLog(@"---start---");
    
    // 获取主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 使用异步函数封装三个任务
    dispatch_async(queue, ^{
        NSLog(@"任务1---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:2.0]; // 模拟运行时间
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0]; // 模拟运行时间
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.3]; // 模拟运行时间
    });
    
    NSLog(@"---end---");
}

// 只执行一次,在主线程中执行
- (void)runOnce
{
    NSLog(@"---start---");
    
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        NSLog(@"任务one---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    
    NSLog(@"---end---");
}


// 延迟执行,自定义执行队列
- (void)runAfter
{
    NSLog(@"---start---");
    
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_after(time, queue, ^{
        NSLog(@"任务 after---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:3.0]; // 模拟运行时间
    });
    
    NSLog(@"---end---");
}


// 自定义dispatch_queue_t(如要要自定义queue,可以用dispatch_queue_create方法)
dispatch_queue_t urls_queue = dispatch_queue_create("http://blog.csdn.net/potato512", NULL);
dispatch_async(urls_queue, ^{
        // your code
        
        [self showCount:@(4)];
});

// 分组执行,自定义执行队列(主线程时,顺序执行)
- (void)runGroup
{
    NSLog(@"---start---");
    
    dispatch_group_t group = dispatch_group_create();
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"任务 1---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.3]; // 模拟运行时间
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"任务 2---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0]; // 模拟运行时间
    });
    // 1
//    dispatch_group_notify(group, queue, ^{
//        NSLog(@"任务 汇总---%@", [NSThread currentThread]);
//        [NSThread sleepForTimeInterval:0.5]; // 模拟运行时间
//    });
    // 或2
    dispatch_group_enter(group);
    NSLog(@"任务 汇总---%@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:0.5]; // 模拟运行时间
    dispatch_group_leave(group);
    dispatch_group_async(group, queue, ^{
        NSLog(@"任务 3---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0]; // 模拟运行时间
    });
    // 或3(避免在主线程使用,造成主线程阻塞)
//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
//    dispatch_group_async(group, queue, ^{
//        NSLog(@"任务 3---%@", [NSThread currentThread]);
//        [NSThread sleepForTimeInterval:1.0]; // 模拟运行时间
//    });
    
    NSLog(@"---end---");
}



// 自定义并行队列时,在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
- (void)runBarrier
{
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_queue_t queue = dispatch_queue_create("001", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"任务 1---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.5]; // 模拟运行时间
    });
    dispatch_async(queue, ^{
        NSLog(@"任务 2---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.2]; // 模拟运行时间
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"任务 3---%@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:1.0]; // 模拟运行时间
    });
    for (int i = 0; i < 3; i++)
    {
        dispatch_async(queue, ^{
            NSLog(@"任务 %d---%@", (i + 4), [NSThread currentThread]);
            [NSThread sleepForTimeInterval:0.2]; // 模拟运行时间
        });
    }
}


// 信息量
- (void)runSemaphore
{
    dispatch_queue_t workConcurrentQueue = dispatch_queue_create("cccccccc", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t serialQueue = dispatch_queue_create("sssssssss", DISPATCH_QUEUE_SERIAL);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    for (NSInteger i = 0; i < 10; i++)
    {
        dispatch_async(serialQueue, ^{
            dispatch_async(workConcurrentQueue, ^{
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                NSLog(@"thread-info:%@开始执行任务%d", [NSThread currentThread], (int)i);
                sleep(1);
                NSLog(@"thread-info:%@结束执行任务%d", [NSThread currentThread], (int)i);
                NSLog(@"---");
                dispatch_semaphore_signal(semaphore);
            });
        });
    }
    NSLog(@"主线程...!");
}

注意:

1)开始执行后没有停止方法(慎重使用)

(2)主线程中使用同步会造成死锁


效果图




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

番薯大佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值