iOS中線程管理可以通過以下四種方式
pthread
NSThread
GCD
NSOperationQueue
同步(sync)異步(async)
串行隊列(serial)并行隊列(concurrent)
1.同步(Synchronous) vs 異步(Asychronous)
同步會阻塞線程曾掂,順序執(zhí)行任務(wù)
異步不會阻塞當(dāng)前前程熟妓。mian隊列除外傲宜,在主線程中同步和異步執(zhí)行都會阻塞主線程器瘪,且不會另開線程洞焙,永遠不要使用sync向主隊列中添加任務(wù),
2.串行和并發(fā)隊列
DISPATCH_QUEUE_SERIAL 串行隊列
DISPATCH_QUEUE_CONCURRENT 并發(fā)隊列
3.主隊列和全局并發(fā)隊列
dispatch_get_global_queue 全局并發(fā)隊列
dispatch_get_main_queue 主隊列串行隊列(主隊列中的任務(wù)都會在主線程上執(zhí)行)
同步執(zhí)行串行隊列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);// 串行隊列
NSLog(@"串行隊列中同步執(zhí)行1 - %@", [NSThread currentThread]);
for(int i = 0;i<10;i++){
// 多次向串行隊列同步添加任務(wù)
dispatch_sync(queue, ^{
NSLog(@"串行隊列中同步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
NSLog(@"串行隊列中同步執(zhí)行3 - %@", [NSThread currentThread]);
異步執(zhí)行串行隊列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"串行隊列中異步執(zhí)行1 - %@", [NSThread currentThread]);
// 異步
for(int i = 0;i<10;i++){
dispatch_async(queue, ^{
NSLog(@"串行隊列中異步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
NSLog(@"串行隊列中異步執(zhí)行3 - %@", [NSThread currentThread]);
同步執(zhí)行并行隊列
dispatch_queue_t queue0 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"并發(fā)隊列中同步執(zhí)行1 - %@", [NSThread currentThread]);
for(int i = 0;i<10;i++){
dispatch_sync(queue0, ^{
NSLog(@"并發(fā)隊列中同步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
NSLog(@"并發(fā)隊列中同步執(zhí)行3 - %@", [NSThread currentThread]);
異步執(zhí)行并發(fā)隊列
dispatch_queue_t queue0 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"并發(fā)隊列中異步執(zhí)行1 - %@", [NSThread currentThread]);
for(int i = 0;i<10;i++){
// 多次添加任務(wù)
dispatch_async(queue0, ^{
NSLog(@"并行隊列中異步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
NSLog(@"并發(fā)隊列中異步執(zhí)行3 - %@", [NSThread currentThread]);
異步執(zhí)行主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"主隊列中異步執(zhí)行1 - %@", [NSThread currentThread]);
// 異步
for(int i = 0;i<8;i++){
dispatch_async(queue, ^{
NSLog(@"主隊列中異步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
for(int i = 0;i<5;i++){
NSLog(@"主隊列中異步執(zhí)行3%d - %@",i, [NSThread currentThread]);
}
主隊列中膨疏,即使有異步任務(wù)九火,也會依次在主線程上執(zhí)行,異步任務(wù)會等主線程上的任務(wù)執(zhí)行完再執(zhí)行俱尼。
同步執(zhí)行主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"主隊列中同步執(zhí)行1 - %@", [NSThread currentThread]);
// 同步
for(int i = 0;i<10;i++){
dispatch_sync(queue, ^{
NSLog(@"主隊列中同步執(zhí)行21%d - %@",i, [NSThread currentThread]);
});
}
NSLog(@"主隊列中同步執(zhí)行3 - %@", [NSThread currentThread]);
以上發(fā)生了死鎖
同步和異步?jīng)Q定了是否開啟新線程抖单。mian隊列除外,在主線程中同步和異步執(zhí)行都會阻塞主線程遇八,且不會另開線程矛绘,永遠不要使用sync向主隊列中添加任務(wù)
小結(jié):
同步執(zhí)行 串行隊列 不開啟新線程,在原線程中串行執(zhí)行隊列
同步執(zhí)行 并行隊列 不開啟新線程押蚤,在原線程中串行執(zhí)行隊列
異步執(zhí)行 串行隊列 開啟新線程蔑歌,在新線程中串行執(zhí)行隊列
異步執(zhí)行 并行隊列 開啟多個線程執(zhí)行任務(wù)
補充:
異步執(zhí)行主隊列 不開啟新線程,在原線程中串行執(zhí)行隊列揽碘,主線程任務(wù)執(zhí)行完后任在主線程執(zhí)行想異步執(zhí)行的任務(wù)
死鎖
了解了同步次屠,異步,串行雳刺,并發(fā)后劫灶,看看以下代碼
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"之前1 - %@", [NSThread currentThread]);
// 異步執(zhí)行串行隊列
dispatch_async(queue, ^{
NSLog(@"sync之前2 - %@", NSThread.currentThread);
dispatch_sync(queue, ^{
NSLog(@"sync3 - %@", NSThread.currentThread);
});
NSLog(@"sync之后4 - %@", NSThread.currentThread);
});
NSLog(@"之后5 - %@", NSThread.currentThread);
上面代碼發(fā)生了死鎖,3掖桦,4不執(zhí)行,異步開啟一個線程 執(zhí)行串行隊列 串行隊列里同步會發(fā)生死鎖本昏!同樣的,在主線程中枪汪,以下代碼也發(fā)生了死鎖
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"之前1 - %@", [NSThread currentThread]);
// 同步執(zhí)行串行隊列
dispatch_sync(queue, ^{
NSLog(@"sync之前2 - %@", NSThread.currentThread);
// 再次向串行隊列中添加同步執(zhí)行串行隊列任務(wù)
dispatch_sync(queue, ^{
NSLog(@"sync3 - %@", NSThread.currentThread);
});
NSLog(@"sync之后4 - %@", NSThread.currentThread);
});
NSLog(@"之后5 - %@", NSThread.currentThread);
在主線程中死鎖涌穆,3,4雀久,5都沒有執(zhí)行
在一個線程中串行執(zhí)行的隊列里宿稀,再次添加同步執(zhí)行該隊列,會發(fā)生死鎖赖捌。