線程就像是在程序運行時又另開一條道路去做一些耗時的操作,不能讓所有的操作都堵在主線程那條路上,這樣就像北京的堵車一樣,體驗非常不好。隊列就相當于你修的單行路還是多行路
1.dispatch_queue_t
這個類就像是創建的道路的樣式
通過這個方法來創建一條新的道路,這個方法需要傳2個參數,第一個參數是為隊列添加一個唯一標識,第二個參數是這個隊列的屬性:
DISPATCH_QUEUE_SERIAL(串行(單行道)for Null也是串行)
DISPATCH_QUEUE_CONCURRENT(并行(多行道))
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
串行就是所有加入隊列的操作就是依次執行,看代碼效果吧:
//串行隊列
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
//加入倆個異步操作
dispatch_async(queue, ^{
for(int i=0;i<5;i++ ){
NSLog(@" 1當前線程 %@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for(int i=0;i<5;i++ ){
NSLog(@" 2當前線程 %@",[NSThread currentThread]);
}
});
看下結果,可以看出來是依次執行的先把上一個操作執行完,并且不是在主線程中進行的
2017年1月4日 02-14-06.png
改下代碼
//把之前的方法參數改為并行屬性
dispatch_queue_t queue1 = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
可以看到結果是一起執行,執行的線程編號為3和4倆個線程里,也不是在主線程中進行
2017年1月4日 02-41-53.png
有可能常見的有一個這個, 這是一個系統全局并行隊列
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.dispatch_group_t
就是一個隊列組,把隊列給套起來的感覺,線程里面任務結束會發出一個消息
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 0當前線程 %@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 1當前線程 %@",[NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for(int i=0;i<10;i++ ){
NSLog(@" 2當前線程 %@",[NSThread currentThread]);
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"完成");
});
效果:
2017年1月4日 03-04-04.png
這樣我們可以在完成異步操作的時候做一些想做的事情。
但實際的操作本身網絡請求就是異步的,所以我們要配合下面的方法
//加入組
dispatch_group_enter(group);
//離開組
dispatch_group_leave(group);
//修改后代碼
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
dispatch_group_enter(group);
//延遲調用模擬網絡請求
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"操作一完成");
dispatch_group_leave(group);
});
});
dispatch_group_async(group, queue, ^{
dispatch_group_enter(group);
//延遲調用模擬網絡請求
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"操作二完成");
dispatch_group_leave(group);
});
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"全部完成");
});
可以看出leave和enter得對應上,如果只enter不leave 最后的消息一直不會走
2017年1月4日 04-15-03.png
上面這個操作可以很好處理一個界面多個網絡請求的問題,當所有的網絡請求都結束時會得到通知并進行操作就可以了