iOS 之GCD串行和並發隊列的理解


dispatch_queue_t serialQueue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(serialQueue, ^{
       // NSLog(@"1");
        sleep(3);
        NSLog(@"1");
    });
    dispatch_sync(serialQueue, ^{
        
        sleep(1);
        NSLog(@"2");
        
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"3");
    });
    dispatch_sync(serialQueue, ^{
        sleep(5);
        NSLog(@"4");
    });
    
    dispatch_async(serialQueue, ^{
        
        NSLog(@"5");
    });

 

看看上面的代碼,你猜猜會輸出什么東東?  反正在今天之前我會認為它輸出坑定不是有序的,之前一直認為串行就是一個一個執行,好,第一個是異步,那就異步去吧,第二個同步,同步執行完,去執行第三個,然后.....  同步就執行完,然后執行下一個,異步就不知道什么時候執行完了。

 

哈哈哈哈,今天我不得不對自己的想法勘稱sb。太自以為是了。從中就可以看出我不能理解串行隊列的本質。

那么什么是串行隊列?什么是並行隊列?

  • Concurrent: tasks are dequeued in FIFO order, but run concurrently and can finish in any order.

  • Serial: tasks execute one at a time in FIFO order

並發: 任務以FIFO從序列中移除,然后並發運行,可以按照任何順序完成。它會自動開啟多個線程同時執行任務

串行:  任務以FIFO從序列中一個一個執行。一次只調度一個任務,隊列中的任務一個接着一個地執行(一個任務執行完畢后,再執行下一個任務)而且只會開啟一條線程

為了再次證實串行隊列中只有一個線程執行任務:

dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_SERIAL);
    
    for (int i = 0; i< 10;i++){
        // 10個異步
        dispatch_async(queue, ^{
            NSLog(@"%@--%d",[NSThread currentThread], i);
        });
    }

 

我們可以發現thread的地址是一樣的,那就證實了serial queue只有一個線程執行任務。然后我們測試一下並發隊列

dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i< 10;i++){
        // 10個異步
        dispatch_async(queue, ^{
            NSLog(@"%@--%d",[NSThread currentThread], i);
        });
    }

 

由上圖可以看出並發隊列中是有多個線程執行任務的。

 

比較上面兩個程序,我們僅僅是創建了兩個不同類型的queue,但是結果迥然不同,並發會開啟多個線程,執行的順序我們無法控制,至於那個線程執行那個任務由隊列決定,哪個任務先完成由CPU和操作系統決定,並且並發隊列中的線程是可以重復利用(線程池),這也是可以理解的,但是下面:

dispatch_queue_t queue = dispatch_queue_create("com.lai.www", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i< 10;i++){
        // 10個異步
        dispatch_sync(queue, ^{
            NSLog(@"%@--%d",[NSThread currentThread], i);
        });
    }

 

發現並發只能在異步函數下有效,name=main ,還不會創建新線程。所有的任務依次在主線程上執行。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM