GCD 控制線程數(shù)量
GCD 不像NSOperation 那樣有直接提供線程數(shù)量控制方法劫拗,但是通過GCD的semaphore 功能一樣可以達(dá)到控制線程數(shù)量的效果实束。
- dispatch_semaphore_create(long value);利用給定的輸出時創(chuàng)建一個新的可計(jì)數(shù)的信號量
- dispatch_semaphore_wait(dispatch_semaphore_t dsema,dispatch_time_t timeout);如果信號量大于0,信號量減1哟玷,執(zhí)行程序纵穿。否則等待信號量
- dispatch_semaphore_signal(dispatch_semaphore_t dsema);增加信號量
信號量其實(shí)就是用來保證訪問資源的線程數(shù)蓖柔,當(dāng)信號量大于等于1時,資源可以訪問闸昨,否則無法訪問資源蚯斯,直到其它線程釋放資源。
這里主要有三個函數(shù):
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //信號量-1
long dispatch_semaphore_signal(dispatch_semaphore_t dsema); //信號量+1
// 控制線程數(shù)量
- (void)runMaxThreadCountWithGCD
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentRunMaxThreadCountWithGCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t serialQueue = dispatch_queue_create("serialRunMaxThreadCountWithGCD", DISPATCH_QUEUE_SERIAL);
// 創(chuàng)建一個semaphore,并設(shè)置最大信號量饵较,最大信號量表示最大線程數(shù)量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
// 使用循環(huán)往串行隊(duì)列 serialQueue 增加 10 個任務(wù)
for (int i = 0; i < 10 ; i++) {
dispatch_async(serialQueue, ^{
// 只有當(dāng)信號量大于 0 的時候溉跃,線程將信號量減 1,程序向下執(zhí)行
// 否則線程會阻塞并且一直等待告抄,直到信號量大于 0
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(concurrentQueue, ^{
NSLog(@"%@ 執(zhí)行任務(wù)一次 i = %d",[NSThread currentThread],i);
// 當(dāng)線程任務(wù)執(zhí)行完成之后撰茎,發(fā)送一個信號,增加信號量打洼。
dispatch_semaphore_signal(semaphore);
});
});
}
NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
}
執(zhí)行結(jié)果如下龄糊,只有 number 3 和 number 4 這 2 個線程在執(zhí)行
<nsthread: 0x60c00007c600>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束
<nsthread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次 i = 0
<nsthread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次 i = 1
<nsthread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次 i = 3
<nsthread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次 i = 2
<nsthread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次 i = 4
<nsthread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次 i = 5
<nsthread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次 i = 6
<nsthread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次 i = 7
<nsthread: 0x60c00027a340>{number = 3, name = (null)} 執(zhí)行任務(wù)一次 i = 8
<nsthread: 0x608000263a00>{number = 4, name = (null)} 執(zhí)行任務(wù)一次 i = 9</nsthread: 0x608000263a00></nsthread: 0x60c00027a340></nsthread: 0x608000263a00></nsthread: 0x60c00027a340></nsthread: 0x608000263a00></nsthread: 0x60c00027a340></nsthread: 0x608000263a00></nsthread: 0x60c00027a340></nsthread: 0x608000263a00></nsthread: 0x60c00027a340></nsthread: 0x60c00007c600>
GCD 任務(wù)分組
GCD 的 dispatch_group_t 功能可以將多個任務(wù)分組,等待分組里面的所有任務(wù)執(zhí)行完成之后募疮,GCD 的 dispatch_group_notify 方法可以通知炫惩。通常會配合一些常見的場景來考察,比如同時上傳 10 張圖片阿浓,全部上傳完成后通知用戶他嚷。
// 任務(wù)分組
- (void)runGroupWithGCD
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("runGroupWithGCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
for (int i = 0; i < 10 ; i++) {
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"%@ 執(zhí)行任務(wù)一次",[NSThread currentThread]);
});
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
});
}
將所有的任務(wù)都加入 group ,等待所有的任務(wù)執(zhí)行完成后,dispatch_group_notify 會被調(diào)用筋蓖。
<nsthread: 0x608000265180>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x604000079a40>{number = 6, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x60c000268780>{number = 5, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x60c000267dc0>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000265080>{number = 9, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x600000265480>{number = 7, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x60c00007f9c0>{number = 8, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264f40>{number = 10, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x604000079a40>{number = 6, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000265180>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x60000006d180>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束</nsthread: 0x60000006d180></nsthread: 0x608000265180></nsthread: 0x604000079a40></nsthread: 0x608000264f40></nsthread: 0x60c00007f9c0></nsthread: 0x600000265480></nsthread: 0x608000265080></nsthread: 0x60c000267dc0></nsthread: 0x60c000268780></nsthread: 0x604000079a40></nsthread: 0x608000265180>
GCD 任務(wù)分組和線程數(shù)量控制
利用 GCD 的 dispatch_group_t 和 semaphore 功能卸耘,我們可以做到控制線程數(shù)量,并且在所有任務(wù)執(zhí)行完成之后得到通知粘咖。
// 任務(wù)分組 + 線程數(shù)量控制
- (void)runMaxCountInGroupWithGCD
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("runGroupWithGCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
for (int i = 0; i < 10 ; i++) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"%@ 執(zhí)行任務(wù)一次",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"%@ 執(zhí)行任務(wù)結(jié)束",[NSThread currentThread]);
});
}
執(zhí)行之后蚣抗,我們可以看到既控制了線程數(shù)量,也在執(zhí)行任務(wù)完成之后得到了通知瓮下。
<nsthread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x608000264780>{number = 4, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x604000269b40>{number = 3, name = (null)} 執(zhí)行任務(wù)一次
<nsthread: 0x60400007aa40>{number = 1, name = main} 執(zhí)行任務(wù)結(jié)束</nsthread: 0x60400007aa40></nsthread: 0x604000269b40></nsthread: 0x608000264780></nsthread: 0x604000269b40></nsthread: 0x608000264780></nsthread: 0x608000264780></nsthread: 0x608000264780></nsthread: 0x604000269b40></nsthread: 0x608000264780></nsthread: 0x604000269b40>