iOS多線程dispatch_queue_t 和dispatch_group_t

線程就像是在程序運行時又另開一條道路去做一些耗時的操作,不能讓所有的操作都堵在主線程那條路上,這樣就像北京的堵車一樣,體驗非常不好。隊列就相當于你修的單行路還是多行路

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

上面這個操作可以很好處理一個界面多個網絡請求的問題,當所有的網絡請求都結束時會得到通知并進行操作就可以了

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容