- 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)}
文件已全部移動完畢