- 1.dispatch_apply函数作用:把一项任务提交到队列中多次执行,具体是串行执行还是并行执行由队列本身决定
注意:dispatch_apply不会立即返回,在执行完毕后才会返回,是同步的调用
void dispatch_apply(size_t iterations, dispatch_queue_t queue,
DISPATCH_NOESCAPE void (^block)(size_t));
参数 :
size_t iterations: 执行的次数
dispatch_queue_t queue: 提交的队列
block 执行的任务
size_t block中每次任务执行的索引
那么,何时使用这个函数呢?从它的功能不难看出,如果我们可以把不相关的循环提交到后台线程并行执行,并且循环任务调度到后台执行的效率提高,能抵消掉队列调度本身的开销,那么效率会显著提高。
例子:从一个文件夹中移动文档到另一个文件夹的操作
分析:移动文件这种操作应该在后台执行的,移动完成后如果需要通知用户,可以在dispatch_apply代码后面操作
因为dispatch_apply会阻塞主线程,而下文又与dispatch_apply的执行结果无关,所以可以在异步队列中掉dispatch_apply,然后执行完成后进行通知
NSString *sourceFile = @"/Users/mofeini/Desktop/toImage"; // 源文件目录
NSString *targetFile = @"/Users/mofeini/Desktop/to"; // 目标文件路面
NSArray *sourceFileSubPaths = [[NSFileManager defaultManager] subpathsAtPath:sourceFile];
NSInteger count = sourceFileSubPaths.count;
// 开启子线程和主线程一起并发完成任务
dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t i) {
NSString *filePath = [targetFile stringByAppendingPathComponent:sourceFileSubPaths[i]];
NSString *toFilePath = [targetFile stringByAppendingPathComponent:sourceFileSubPaths[i]];
[[NSFileManager defaultManager] moveItemAtPath:filePath toPath:toFilePath error:nil];
NSLog(@"%ld, 当前线程%@", i, [NSThread currentThread]);
});
// 文件全部移动完成后通知用户
NSLog(@"文件已全部移动完毕");
打印结果
>索引== 2, 当前线程<NSThread: 0x600000078640>{number = 3, name = (null)}
索引==1, 当前线程<NSThread: 0x608000076880>{number = 4, name = (null)}
索引== 0, 当前线程<NSThread: 0x610000074280>{number = 1, name = main}
索引==3, 当前线程<NSThread: 0x6000000785c0>{number = 5, name = (null)}
文件已全部移动完毕