多個(gè)任務(wù)同時(shí)執(zhí)行倒脓,全部執(zhí)行完畢再執(zhí)行其他的操作
(1)dispatch_group_async撑螺、dispatch_group_notify結(jié)合使用
/// 隊(duì)列組
dispatch_group_t group = dispatch_group_create();
/// 并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"任務(wù)一:%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任務(wù)二:%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任務(wù)三:%@",[NSThread currentThread]);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"所有任務(wù)執(zhí)行完畢:%@",[NSThread currentThread]);
});
#打印結(jié)果:
任務(wù)一、任務(wù)二崎弃、任務(wù)三(順序不一定甘晤,因?yàn)槎际钱惒酵瑫r(shí)執(zhí)行的)都執(zhí)行完成,才執(zhí)行:所有任務(wù)執(zhí)行完畢
(2) 使用柵欄函數(shù)
/// 自定義并發(fā)隊(duì)列
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任務(wù)一:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)二:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)三:%@",[NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"所有任務(wù)執(zhí)行完畢:%@",[NSThread currentThread]);
});
# 打印結(jié)果:
2020-10-13 16:24:17.926220+0800 ThreadingDemo[26902:6624494] 任務(wù)二:{number = 4, name = (null)}
2020-10-13 16:24:17.926227+0800 ThreadingDemo[26902:6624499] 任務(wù)一:{number = 6, name = (null)}
2020-10-13 16:24:17.926220+0800 ThreadingDemo[26902:6624495] 任務(wù)三:{number = 5, name = (null)}
2020-10-13 16:24:17.926396+0800 ThreadingDemo[26902:6624495] 所有任務(wù)執(zhí)行完畢:{number = 5, name = (null)}
以上的兩種寫(xiě)法對(duì)于任務(wù)是同步的饲做,是沒(méi)有問(wèn)題的线婚。
但是如果對(duì)于異步執(zhí)行的任務(wù),則會(huì)達(dá)不到順序執(zhí)行的盆均,比如網(wǎng)絡(luò)請(qǐng)求.
因?yàn)楫惒阶靡粒?qǐng)求還沒(méi)回來(lái),dispatch_group_notify或dispatch_barrier_async已經(jīng)執(zhí)行了
如果任務(wù)是異步的,可以使用信號(hào)量或者dispatch_group_enter居砖、dispatch_group_leave事項(xiàng)
# 比如下方任務(wù)是異步的網(wǎng)絡(luò)請(qǐng)求虹脯,那么柵欄函數(shù)也是控制不住執(zhí)行順序的
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self requestNetworkWithCallback:^{
NSLog(@"任務(wù)1");
}];
});
dispatch_async(queue, ^{
[self requestNetworkWithCallback:^{
NSLog(@"任務(wù)2");
}];
});
dispatch_async(queue, ^{
[self requestNetworkWithCallback:^{
NSLog(@"任務(wù)3");
}];
});
dispatch_barrier_async(queue, ^{
NSLog(@"任務(wù)全部執(zhí)行完成");
});
}
/// 異步任務(wù):模擬網(wǎng)絡(luò)請(qǐng)求
- (void)requestNetworkWithCallback:(void(^)(void))callback {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
if (callback) {
callback();
}
});
}
# 打印結(jié)果:(“任務(wù)全部執(zhí)行完成”肯定都是先執(zhí)行的)
2020-10-14 09:36:32.053314+0800 ThreadingDemo[45423:6822309] 任務(wù)全部執(zhí)行完成
2020-10-14 09:36:34.053708+0800 ThreadingDemo[45423:6822308] 任務(wù)1
2020-10-14 09:36:34.053729+0800 ThreadingDemo[45423:6822310] 任務(wù)2
2020-10-14 09:36:34.053733+0800 ThreadingDemo[45423:6822307] 任務(wù)3
(3)信號(hào)量
信號(hào)量的作用:線程同步、線程加鎖
dispatch_semaphore_t dispatch_semaphore_create(long value):方法接收一個(gè)long類型的參數(shù)奏候,返回一個(gè)dispatch_semaphore_t類型的信號(hào)量循集,值為傳入的參數(shù)
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout):接收一個(gè)信號(hào)和時(shí)間值,若信號(hào)的量為0蔗草,則會(huì)阻塞當(dāng)前線程咒彤,知道信號(hào)量大于0或者經(jīng)過(guò)輸入的時(shí)間值;若信號(hào)量大于0咒精,則會(huì)使信號(hào)量減1并返回镶柱,程序繼續(xù)往下執(zhí)行
long dispatch_semaphore_signal(dispatch_semaphore_t dsema):使信號(hào)量加1并返回
# 對(duì)于多個(gè)任務(wù)同時(shí)進(jìn)行,執(zhí)行完成后再執(zhí)行其他任務(wù)模叙,用單個(gè)信號(hào)量完成不了
# 只能是一個(gè)個(gè)任務(wù)執(zhí)行完成再執(zhí)行另外一個(gè)任務(wù)
# 使用場(chǎng)景:多張圖片歇拆,一張張上傳
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
/// 創(chuàng)建信號(hào)量,并設(shè)置為0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self requestNetworkWithTime:1 callback:^{
NSLog(@"任務(wù)1");
/// 信號(hào)量 + 1
dispatch_semaphore_signal(semaphore);
}];
/// 判斷如果信號(hào)量為0范咨,則阻塞等待
/// 信號(hào)量大于1故觅,則會(huì)使信號(hào)量減 1,程序繼續(xù)往下執(zhí)行
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"任務(wù)2");
});
}
/// 異步任務(wù):模擬網(wǎng)絡(luò)請(qǐng)求
- (void)requestNetworkWithTime:(NSInteger )time callback:(void(^)(void))callback {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:time];
if (callback) {
callback();
}
});
}
# 打印結(jié)果:
2020-10-14 13:51:20.956845+0800 ThreadingDemo[59313:7012870] 任務(wù)1
2020-10-14 13:51:20.957029+0800 ThreadingDemo[59313:7012871] 任務(wù)2
# 創(chuàng)建多個(gè)信號(hào)渠啊,異步同時(shí)執(zhí)行任務(wù)输吏,都執(zhí)行完成再執(zhí)行其他操作
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
/// 創(chuàng)建信號(hào)1
dispatch_semaphore_t semap = dispatch_semaphore_create(0);
[self requestNetworkWithTime:2 callback:^{
NSLog(@"任務(wù)1");
dispatch_semaphore_signal(semap);
}];
dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);
});
dispatch_group_async(group, queue, ^{
/// 創(chuàng)建信號(hào)2
dispatch_semaphore_t semap = dispatch_semaphore_create(0);
[self requestNetworkWithTime:1 callback:^{
NSLog(@"任務(wù)2");
dispatch_semaphore_signal(semap);
}];
dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"全部執(zhí)行完成");
});
}
/// 異步任務(wù):模擬網(wǎng)絡(luò)請(qǐng)求
- (void)requestNetworkWithTime:(NSInteger )time callback:(void(^)(void))callback {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:time];
if (callback) {
callback();
}
});
}
# 打印結(jié)果:
2020-10-14 15:42:34.781421+0800 ThreadingDemo[76163:7169489] 任務(wù)2
2020-10-14 15:42:35.781343+0800 ThreadingDemo[76163:7169490] 任務(wù)1
2020-10-14 15:42:35.781643+0800 ThreadingDemo[76163:7169495] 全部執(zhí)行完成
(4)dispatch_group_enter/leave
dispatch_group_enter 和 dispatch_group_leave 必須成對(duì)出現(xiàn),否則會(huì)造成“死鎖”
dispatch_group_wait:如果enter數(shù)不等于leave數(shù)替蛉,則線程阻塞等待贯溅,若enter數(shù)與leave數(shù)相等則繼續(xù)往下執(zhí)行
dispatch_group_notify:只有enter數(shù)和leave數(shù)相等,才會(huì)執(zhí)行
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[self requestNetworkWithTime:1 callback:^{
NSLog(@"任務(wù)1");
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self requestNetworkWithTime:2 callback:^{
NSLog(@"任務(wù)2");
dispatch_group_leave(group);
}];
/// 等待任務(wù)1躲查、任務(wù)2執(zhí)行完畢
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
[self requestNetworkWithTime:2 callback:^{
NSLog(@"任務(wù)3");
dispatch_group_leave(group);
}];
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"全部執(zhí)行完成");
});
}
/// 異步任務(wù):模擬網(wǎng)絡(luò)請(qǐng)求
- (void)requestNetworkWithTime:(NSInteger )time callback:(void(^)(void))callback {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:time];
if (callback) {
callback();
}
});
}
# 打印結(jié)果:
2020-10-14 15:18:03.405899+0800 ThreadingDemo[74573:7126913] 任務(wù)1
2020-10-14 15:18:04.407338+0800 ThreadingDemo[74573:7126917] 任務(wù)2
2020-10-14 15:18:06.410904+0800 ThreadingDemo[74573:7126917] 任務(wù)3
2020-10-14 15:18:06.411069+0800 ThreadingDemo[74573:7126917] 全部執(zhí)行完成
補(bǔ)充:柵欄函數(shù)dispatch_barrier使用教程
dispatch_barrier_async:無(wú)需等待柵欄函數(shù)執(zhí)行完成它浅,會(huì)繼續(xù)往下走(任務(wù)執(zhí)行順序:柵欄前的任務(wù)===》柵欄函數(shù) ====》 柵欄函數(shù)后的任務(wù))
dispatch_barrier_sync:需要等待柵欄函數(shù)執(zhí)行完才會(huì)執(zhí)行柵欄后面的任務(wù)
注意:
(1)柵欄必須在并發(fā)隊(duì)列執(zhí)行 ,并且不能使用全局隊(duì)列熙含,否則柵欄函數(shù)就不起作用;
dispatch_barrier_async 等同于 dispatch_async , dispatch_barrier_sync 等同于 dispatch_sync
(2)理解的時(shí)候,必須要區(qū)分哪些是任務(wù)艇纺,哪些是普通代碼
# dispatch_barrier_async
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"start");
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任務(wù)1");
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)2");
});
/// 因?yàn)槭菛艡诋惒皆蹙玻詵艡诤瘮?shù)和柵欄函數(shù)后面的任務(wù)都
dispatch_barrier_async(queue, ^{
NSLog(@"===== barrier ====");
});
NSLog(@"mid");
dispatch_async(queue, ^{
NSLog(@"任務(wù)3");
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)4");
});
NSLog(@"last");
}
打印結(jié)果:
2020-10-13 16:02:03.843934+0800 ThreadingDemo[26494:6576066] start
2020-10-13 16:02:03.844143+0800 ThreadingDemo[26494:6576066] mid
2020-10-13 16:02:03.844189+0800 ThreadingDemo[26494:6576341] 任務(wù)1
2020-10-13 16:02:03.844182+0800 ThreadingDemo[26494:6576343] 任務(wù)2
2020-10-13 16:02:03.844231+0800 ThreadingDemo[26494:6576066] last
2020-10-13 16:02:03.844300+0800 ThreadingDemo[26494:6576343] ===== barrier ====
2020-10-13 16:02:03.844375+0800 ThreadingDemo[26494:6576343] 任務(wù)3
2020-10-13 16:02:03.844381+0800 ThreadingDemo[26494:6576341] 任務(wù)4
# dispatch_barrier_sync
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"start");
dispatch_queue_t queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任務(wù)1");
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)2");
});
/// 因?yàn)槭峭綎艡冢瑘?zhí)行順序:柵欄前 ===》柵欄函數(shù) ====》 柵欄后
dispatch_barrier_sync(queue, ^{
NSLog(@"===== barrier ====");
});
NSLog(@"mid");
dispatch_async(queue, ^{
NSLog(@"任務(wù)3");
});
dispatch_async(queue, ^{
NSLog(@"任務(wù)4");
});
NSLog(@"last");
}
打印結(jié)果:
2020-10-13 16:02:42.629822+0800 ThreadingDemo[26527:6577198] start
2020-10-13 16:02:42.630035+0800 ThreadingDemo[26527:6577356] 任務(wù)1
2020-10-13 16:02:42.630037+0800 ThreadingDemo[26527:6577360] 任務(wù)2
2020-10-13 16:02:42.630155+0800 ThreadingDemo[26527:6577198] ===== barrier ====
2020-10-13 16:02:42.630224+0800 ThreadingDemo[26527:6577198] mid
2020-10-13 16:02:42.630310+0800 ThreadingDemo[26527:6577198] last
2020-10-13 16:02:42.630327+0800 ThreadingDemo[26527:6577360] 任務(wù)3
2020-10-13 16:02:42.630374+0800 ThreadingDemo[26527:6577356] 任務(wù)4