一、同步執(zhí)行 + 主隊(duì)列
/**
* 同步執(zhí)行 + 主隊(duì)列
* 特點(diǎn)(主線(xiàn)程調(diào)用):互等卡主不執(zhí)行。
* 特點(diǎn)(其他線(xiàn)程調(diào)用):不會(huì)開(kāi)啟新線(xiàn)程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
*/
- (void)syncMain {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當(dāng)前線(xiàn)程
NSLog(@"開(kāi)啟");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束");
}
運(yùn)行結(jié)果:
currentThread---<NSThread: 0x600001904240>{number = 1, name = main}
開(kāi)啟
線(xiàn)程死鎖。為什么呢?
- (void)syncMain {} ----> 任務(wù)A,GCD同步任務(wù) ----> 任務(wù)B
??????任務(wù)A在主隊(duì)列,并且已經(jīng)開(kāi)始執(zhí)行(打印出currentThread),這個(gè)時(shí)候任務(wù)B被加入到主隊(duì)列中,并且同步執(zhí)行,且不能開(kāi)新的線(xiàn)程。
??????任務(wù)B得等Block函數(shù)執(zhí)行完成,才能返回,然而主隊(duì)列是串行的,得等任務(wù)A執(zhí)行完才能去執(zhí)行任務(wù)B的Block。
??????造成了任務(wù)A在等任務(wù)B完成才能繼續(xù)執(zhí)行,但是串行隊(duì)列中,又不能讓任務(wù)B在任務(wù)A未完成之前開(kāi)始執(zhí)行,相互等待,造成了死鎖。
二、同步執(zhí)行 + 并發(fā)隊(duì)列
/**
* 同步執(zhí)行 + 并發(fā)隊(duì)列
* 特點(diǎn):在當(dāng)前線(xiàn)程中執(zhí)行任務(wù),不會(huì)開(kāi)啟新線(xiàn)程,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
*/
- (void)syncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當(dāng)前線(xiàn)程
NSLog(@"開(kāi)啟");
dispatch_queue_t queue = dispatch_queue_create("syncConcurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束");
}
運(yùn)行結(jié)果:
currentThread---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
開(kāi)啟
1---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
2---<NSThread: 0x600003e0c1c0>{number = 1, name = main}
結(jié)束
三、異步執(zhí)行 + 并發(fā)隊(duì)列
/**
* 異步執(zhí)行 + 并發(fā)隊(duì)列
* 特點(diǎn):可以開(kāi)啟多個(gè)線(xiàn)程,任務(wù)交替(同時(shí))執(zhí)行。
*/
- (void)asyncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當(dāng)前線(xiàn)程
NSLog(@"開(kāi)啟");
dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束");
}
運(yùn)行結(jié)果:
currentThread---<NSThread: 0x600000d48980>{number = 1, name = main}
開(kāi)啟
結(jié)束
1---<NSThread: 0x600000d019c0>{number = 5, name = (null)}
2---<NSThread: 0x600000d00500>{number = 6, name = (null)}
四、同步執(zhí)行 + 串行隊(duì)列
/**
* 同步執(zhí)行 + 串行隊(duì)列
* 特點(diǎn):不會(huì)開(kāi)啟新線(xiàn)程,在當(dāng)前線(xiàn)程執(zhí)行任務(wù)。任務(wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
*/
- (void)syncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當(dāng)前線(xiàn)程
NSLog(@"開(kāi)啟");
dispatch_queue_t queue = dispatch_queue_create("syncSerial", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束");
}
運(yùn)行結(jié)果:
currentThread---<NSThread: 0x600001284240>{number = 1, name = main}
開(kāi)啟
1---<NSThread: 0x600001284240>{number = 1, name = main}
2---<NSThread: 0x600001284240>{number = 1, name = main}
結(jié)束
五、異步執(zhí)行 + 串行隊(duì)列
/**
* 異步執(zhí)行 + 串行隊(duì)列
* 特點(diǎn):會(huì)開(kāi)啟新線(xiàn)程,但是因?yàn)槿蝿?wù)是串行的,執(zhí)行完一個(gè)任務(wù),再執(zhí)行下一個(gè)任務(wù)。
*/
- (void)asyncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當(dāng)前線(xiàn)程
NSLog(@"開(kāi)啟");
dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"結(jié)束");
}
運(yùn)行結(jié)果:
currentThread---<NSThread: 0x6000025ac580>{number = 1, name = main}
開(kāi)啟
結(jié)束
1---<NSThread: 0x6000025fc680>{number = 4, name = (null)}
2---<NSThread: 0x6000025fc680>{number = 4, name = (null)}
六、其他函數(shù)用法
1、dispatch_after
- (void)GCDDelay {
NSLog(@"current_%@",[NSThread currentThread]);
//主隊(duì)列延時(shí)
dispatch_time_t when_main = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_main, dispatch_get_main_queue(), ^{
NSLog(@"main_%@",[NSThread currentThread]);
});
//全局隊(duì)列延時(shí)
dispatch_time_t when_global = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_global, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"global_%@",[NSThread currentThread]);
});
//自定義隊(duì)列延時(shí)
dispatch_queue_t customeQue = dispatch_queue_create("customeQue", DISPATCH_QUEUE_SERIAL);
dispatch_time_t when_global_custom = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_global_custom, customeQue, ^{
NSLog(@"when_global_custom_%@",[NSThread currentThread]);
});
}
current_<NSThread: 0x600003fe8980>{number = 1, name = main}
main_<NSThread: 0x600003fe8980>{number = 1, name = main}
when_global_custom_<NSThread: 0x600003fa58c0>{number = 7, name = (null)}
global_<NSThread: 0x600003fad280>{number = 5, name = (null)}
??????我們可以看到,當(dāng)隊(duì)列是主隊(duì)列時(shí),任務(wù)是在主線(xiàn)程執(zhí)行;當(dāng)隊(duì)列為全局或自定義時(shí),任務(wù)是在子線(xiàn)程中執(zhí)行
2、dispatch_once
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"current_%@",[NSThread currentThread]);
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
current_<NSThread: 0x600001cf8900>{number = 1, name = main}
<NSThread: 0x600001cf8900>{number = 1, name = main}
??????程序運(yùn)行期間,只會(huì)執(zhí)行一次打印,任務(wù)在主線(xiàn)程中執(zhí)行
3、dispatch_group_async & dispatch_group_notify
- (void)GCDGroup {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"3---%@",[NSThread currentThread]);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x6000032a0980>{number = 1, name = main}
end_<NSThread: 0x6000032a0980>{number = 1, name = main}
1---<NSThread: 0x6000032a8880>{number = 6, name = (null)}
2---<NSThread: 0x6000032ed4c0>{number = 3, name = (null)}
3---<NSThread: 0x6000032ed4c0>{number = 3, name = (null)}
dispatch_group_async在dispatch_get_global_queue時(shí)會(huì)開(kāi)辟新的線(xiàn)程執(zhí)行任務(wù),任務(wù)會(huì)在子線(xiàn)程中執(zhí)行
dispatch_group_notify只會(huì)在dispatch_group_async都執(zhí)行完后才會(huì)執(zhí)行
4、dispatch_barrier_async
- (void)GCDBarrier {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
//同步sync
dispatch_barrier_sync(myQueue, ^{
NSLog(@"barrier---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"3---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"4---%@",[NSThread currentThread]);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
myQueue為自定義時(shí):
start_<NSThread: 0x600001044980>{number = 1, name = main}
2---<NSThread: 0x600001008a80>{number = 6, name = (null)}
1---<NSThread: 0x60000104db80>{number = 5, name = (null)}
barrier---<NSThread: 0x600001044980>{number = 1, name = main}
end_<NSThread: 0x600001044980>{number = 1, name = main}
3---<NSThread: 0x60000104db80>{number = 5, name = (null)}
4---<NSThread: 0x600001008a80>{number = 6, name = (null)}
myQueue為:dispatch_get_global_queue(0,0)時(shí)
start_<NSThread: 0x600001f90a00>{number = 1, name = main}
barrier---<NSThread: 0x600001f90a00>{number = 1, name = main}
1---<NSThread: 0x600001fdacc0>{number = 6, name = (null)}
2---<NSThread: 0x600001fd5340>{number = 7, name = (null)}
3---<NSThread: 0x600001fdacc0>{number = 6, name = (null)}
end_<NSThread: 0x600001f90a00>{number = 1, name = main}
4---<NSThread: 0x600001fc5080>{number = 4, name = (null)}
- 當(dāng)隊(duì)列為
自定義時(shí),使用dispatch_barrier_sync ()后,任務(wù)3、4必須等任務(wù)1、2執(zhí)行完后才能執(zhí)行 - 當(dāng)隊(duì)列是
dispatch_get_global_queue(0,0)時(shí),就算使用了dispatch_barrier_sync (),執(zhí)行順序隨機(jī)不固定 - 當(dāng)隊(duì)列是
dispatch_get_main_queue()時(shí),死鎖
5、dispatch_apply
- (void)GCDApply {
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//重復(fù)執(zhí)行
dispatch_apply(5, myQueue, ^(size_t i) {
NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
});
}
myQueue為串行:
start_<NSThread: 0x600003d70980>{number = 1, name = main}
第0次_<NSThread: 0x600003d70980>{number = 1, name = main}
第1次_<NSThread: 0x600003d70980>{number = 1, name = main}
第2次_<NSThread: 0x600003d70980>{number = 1, name = main}
第3次_<NSThread: 0x600003d70980>{number = 1, name = main}
第4次_<NSThread: 0x600003d70980>{number = 1, name = main}
end_<NSThread: 0x600003d70980>{number = 1, name = main}
myQueue為并行:
start_<NSThread: 0x6000009d0a00>{number = 1, name = main}
第3次_<NSThread: 0x600000995900>{number = 6, name = (null)}
第2次_<NSThread: 0x6000009d7540>{number = 4, name = (null)}
第0次_<NSThread: 0x6000009d0a00>{number = 1, name = main}
第1次_<NSThread: 0x600000984300>{number = 7, name = (null)}
第4次_<NSThread: 0x6000009852c0>{number = 5, name = (null)}
end_<NSThread: 0x6000009d0a00>{number = 1, name = main}
- 用于重復(fù)執(zhí)行某個(gè)任務(wù)
- 任務(wù)隊(duì)列是
串行隊(duì)列時(shí),重復(fù)執(zhí)行的任務(wù)會(huì)按順序執(zhí)行 - 任務(wù)隊(duì)列是
并行隊(duì)列時(shí),重復(fù)執(zhí)行的任務(wù)會(huì)并發(fā)執(zhí)行
6、dispatch_semaphore_create & dispatch_semaphore_wait & dispatch_semaphore_signal
- (void)GCDSemaphor {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建信號(hào)量,初始值不能小于0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//重復(fù)執(zhí)行
dispatch_apply(5, myQueue, ^(size_t i) {
//等待降低信號(hào)量,也就是信號(hào)量-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
//提高信號(hào)量,也就是信號(hào)量+1
dispatch_semaphore_signal(semaphore);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第0次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第1次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第2次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第3次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
第4次_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
end_<NSThread: 0x600003bf0bc0>{number = 1, name = main}
異步任務(wù)使用
- (void)GCDSemaphorAsync {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
//創(chuàng)建信號(hào)量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(myQueue, ^{
NSLog(@"第一次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第一次任務(wù)結(jié)束_%@",[NSThread currentThread]);
//會(huì)將信號(hào)量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(myQueue, ^{
NSLog(@"第二次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第二次任務(wù)結(jié)束_%@",[NSThread currentThread]);
//會(huì)將信號(hào)量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(myQueue, ^{
NSLog(@"第三次任務(wù)開(kāi)始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第三次任務(wù)結(jié)束_%@",[NSThread currentThread]);
//會(huì)將信號(hào)量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"end_%@",[NSThread currentThread]);
}
start_<NSThread: 0x600002eb0a00>{number = 1, name = main}
第一次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第一次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第二次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第二次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第三次任務(wù)開(kāi)始_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
第三次任務(wù)結(jié)束_<NSThread: 0x600002eb9f40>{number = 6, name = (null)}
end_<NSThread: 0x600002eb0a00>{number = 1, name = main}
-
dispatch_semaphore_create創(chuàng)建信號(hào)量,初始值不能小于0 -
dispatch_semaphore_wait等待降低信號(hào)量,也就是信號(hào)量-1 -
dispatch_semaphore_signal提高信號(hào)量,也就是信號(hào)量+1 -
dispatch_semaphore_wait和dispatch_semaphore_signal通常配對(duì)使用
主要作用:
- 保持線(xiàn)程同步,將異步執(zhí)行任務(wù)轉(zhuǎn)換為同步執(zhí)行任務(wù)
- 保證線(xiàn)程 安全,為線(xiàn)程加鎖