1. GCD栅栏函数
- 作用:只有当栅栏函数执行完毕后才能执行后面的函数
- 需求:使用栅栏函数规定线程执行顺序
- 注意点:栅栏函数不能使用全局并发队列
使用案例
// 1. 获得并发队列
// 栅栏函数不能使用全局并发队列
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
// 2. 异步函数
dispatch_async(queue, ^{
for (NSInteger i = 0; i< 100; i++) {
NSLog(@"download ----%zd----- %@",i,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i< 100; i++) {
NSLog(@"download2 ----%zd----- %@",i,[NSThread currentThread]);
}
});
// 栅栏函数
dispatch_barrier_async(queue, ^{
NSLog(@"栅栏----------");
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i< 100; i++) {
NSLog(@"download3 ----%zd----- %@",i,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i< 100; i++) {
NSLog(@"download4 ----%zd----- %@",i,[NSThread currentThread]);
}
});
2. GCD快速迭代
for循环遍历数据,是同步的, 串行队列
// 同步
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"%zd-------%@",i,[NSThread currentThread]);
}
GCD快速迭代:
开子线程和主线程一起完成遍历任务,任务的执行是并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
第一参数(<#size_t iterations#>): 要遍历的次数
第二参数(<#dispatch_queue_t _Nonnull queue#>): 队列(必须是并发队列)
第三参数(<#^(size_t)block#> ^(size_t index)): index 为索引
*/
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zd-------%@",index,[NSThread currentThread]);
});
主要代码示例:
//
// ViewController.m
// 02-掌握GCD的快速迭代
//
// Created by wenjim on 17/10/30.
// Copyright © 2017年 WenJim. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) UIButton * btn;
@end
@implementation ViewController
-(UIButton *)btn
{
if (!_btn) {
_btn = [UIButton buttonWithType:UIButtonTypeCustom];
_btn.frame = CGRectMake(self.view.frame.size.width / 2 - 25, self.view.frame.size.height / 2 - 15, 50, 30);
[_btn setTitle:@"点击" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(moveGCDFile) forControlEvents:UIControlEventTouchUpInside];
}
return _btn;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.btn];
}
-(void)forDemo
{
// 同步
for (NSInteger i = 0; i < 10; i++) {
NSLog(@"%zd-------%@",i,[NSThread currentThread]);
}
}
#pragma mark - 开子线程和主线程一起完成遍历任务,任务的执行是并发的
-(void)apply
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
第一参数(<#size_t iterations#>): 要遍历的次数
第二参数(<#dispatch_queue_t _Nonnull queue#>): 队列(并发队列)
第三参数(<#^(size_t)block#> ^(size_t index)): 索引
*/
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zd-------%@",index,[NSThread currentThread]);
});
}
#pragma mark - for 循环 移动文件夹的所有文件
-(void)moveFile
{
// 1. 拿到文件路径
NSString * formStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/testFile";
// 2.获得目标文件路径
NSString * toStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/toFile";
// 3. 得到目录下面的所哟文件
NSFileManager * manager = [NSFileManager defaultManager];
NSArray * arr = [manager subpathsAtPath:formStr];
NSLog(@"文件有:%@",arr);
// 4. 遍历所有文件
for (NSInteger i = 0; i < arr.count; i ++) {
// 4.1 拼接文件全路径
// NSString * formFullStr = [formStr stringByAppendingString:arr[i]];
// 在拼接的时候会自动添加/
NSString * formFullStr = [formStr stringByAppendingPathComponent:arr[i]];
NSLog(@"文件所在路径:%@",formFullStr);
NSString * toFullStr = [toStr stringByAppendingPathComponent:arr[i]];
NSLog(@"移动文件所在路径:%@",toFullStr);
// 4.2 移动文件 formFullStr toFullStr
/*
第一个参数:要剪切文件在哪里
第二个参数:文件应该被存到哪个位置
*/
[manager moveItemAtURL:[NSURL fileURLWithPath:toFullStr] toURL:[NSURL fileURLWithPath:formFullStr] error:nil];
}
}
#pragma mark - GCD方法 移动文件夹的所有文件
-(void)moveGCDFile
{
// 1. 拿到文件路径
NSString * formStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/testFile";
// 2.获得目标文件路径
NSString * toStr = @"/Users/WJim/Desktop/GITEE/DuoXianChengDeXueXi/day12/toFile";
// 3. 得到目录下面的所哟文件
NSFileManager * manager = [NSFileManager defaultManager];
NSArray * arr = [manager subpathsAtPath:formStr];
NSLog(@"文件有:%@",arr);
// 4. 遍历所有文件
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_apply(arr.count, queue, ^(size_t index) {
// 4.1 拼接文件全路径
NSString * formFullStr = [formStr stringByAppendingPathComponent:arr[index]];
NSString * toFullStr = [toStr stringByAppendingPathComponent:arr[index]];
// 4.2 开始移动文件
/*
第一个参数:要剪切文件在哪里
第二个参数:文件应该被存到哪个位置
*/
[manager moveItemAtURL:[NSURL fileURLWithPath:formFullStr] toURL:[NSURL fileURLWithPath:toFullStr] error:nil];
});
}
@end
3. 队列组
- 有这么1种需求
- 首先:分别异步执行2个耗时的操作
- 其次:等2个异步操作都执行完毕后,再回到主线程执行操作
如果想要快速高效地实现上述需求,可以考虑用队列组
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});