1. 程式人生 > >GCD會建立多少個執行緒

GCD會建立多少個執行緒

關於GCD佇列,系統佇列編號有11個,1為主佇列,2為管理佇列,3保留;4-11為8個全域性佇列,優先順序分別為LOW、DEFAULT、HIGH 和 BACKGROUND,4個佇列overcommit為YES,4個為NO;
如果為overcommit佇列,有新任務就會重新開闢新的執行緒,其中    dq->dq_width = UINT32_MAX;表示這些佇列不限制併發數。
任何自己建立的佇列預設都依附於系統的DEFAULT佇列,序列的依附於DISPATCH_ROOT_QUEUE_IDX_DEFAULT_OVERCOMMIT_PRIORITY;並行佇列依附於DISPATCH_ROOT_QUEUE_IDX_DEFAULT_PRIORITY
當然也可以自己再重新設定所依附的佇列。




GCD號稱非常高效,底層用的執行緒池,就會想系統怎麼排程才能更好效,執行緒池會建立多少個執行緒:系統如果建立非常多執行緒,那佇列的意義就沒有了,來個任務就建立執行緒,就不用排隊了,並且如果執行緒過多肯定會伴隨著效能下降。那就測試一下系統到底會建立多少個執行緒


### 一、分別建立10個,100個和10000個並行任務


    NSInteger taskCount = 10/10000/100;
    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue, ^{
            NSLog(@"thread: @", [NSThread currentThread]);
        });
    }
最終通過log看taskCount為10時,執行緒個數大約是八九個,看情況不定;taskCount為100和10000時執行緒num是從3到66,總共64個,64是2的6次方,也比較符合程式的一貫風格;因為任務比較輕,所以當任務比較少時到後面分配任務時前面的任務已經做完,所以會在原來的執行緒上執行任務;一旦任務比較多時,就會全力分配執行緒。


### 二、兩個並行佇列各分配10000個任務


結果依然是64,因為都是依附於DISPATCH_ROOT_QUEUE_IDX_DEFAULT_PRIORITY,DISPATCH_ROOT_QUEUE_IDX_DEFAULT_PRIORITY預設為64,不管他那幾個依附於DISPATCH_ROOT_QUEUE_IDX_DEFAULT_PRIORITY,結果都一樣


### 三、並行佇列設定不同優先順序:


    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue, ^{
            NSLog(@"thread: @", [NSThread currentThread]);
        });
    }


    for (int i = 0; i < taskCount; i++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSLog(@"DISPATCH_QUEUE_PRIORITY_HIGH thread: @", [NSThread currentThread]);
        });
    }
經過測試發現先輸出的是DISPATCH_QUEUE_PRIORITY_DEFAULT(self.queue)的部分然後就開始輸出DISPATCH_QUEUE_PRIORITY_HIGH部分,DISPATCH_QUEUE_PRIORITY_HIGH全部輸出完了後才繼續輸出DISPATCH_QUEUE_PRIORITY_DEFAULT(self.queue);執行緒個數依然為64。


先輸出了DISPATCH_QUEUE_PRIORITY_DEFAULT(self.queue)部分是因為在傳送DISPATCH_QUEUE_PRIORITY_DEFAULT(self.queue)全部任務期間還沒有輪到DISPATCH_QUEUE_PRIORITY_HIGH建立任務,一旦等有了DISPATCH_QUEUE_PRIORITY_HIGH任務就立即執行高優先順序的任務了。




### 四、新增序列佇列:


    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.serialQueue, ^{
            NSLog(@"serialQueue thread: @", [NSThread currentThread]);
        });
    }


    NSInteger taskCount = 10000;
    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue, ^{
            NSLog(@"thread: @", [NSThread currentThread]);
        });
    }


執行緒個數為65個,說明當序列佇列加入時肯定會建立一個執行緒對應;同時建立兩個序列佇列然後就會輸出66個執行緒


### 五、序列佇列重新設定依附於一個非overcommit全域性佇列


    dispatch_set_target_queue(self.serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));
    dispatch_set_target_queue(self.serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
執行緒個數為64但是發現無論依附的是高優先順序還是低優先順序,序列佇列都會從開始分配任務就執行;說明當序列佇列和並行佇列依附於同一並行佇列時,序列佇列的優先順序總是高於並行


### 六、序列佇列獲取全域性佇列時flag處設定為1


不管是蘋果官方文件,還是其他人部落格都會說flag處保留欄位暫時都為0,看到過一段gcd原始碼
dispatch_queue_t
dispatch_get_global_queue(long priority, unsigned long flags)
{
  if (flags & ~DISPATCH_QUEUE_OVERCOMMIT) {
    return NULL;
  }
  return _dispatch_get_root_queue(priority,
      flags & DISPATCH_QUEUE_OVERCOMMIT);
}


從這段原始碼中flags設定為1獲取到的應該是overcommit的佇列,那如果序列佇列依附於overcommit的,那執行緒個數應該是65了;
經測試果然為65,說明flags功能就是來區分獲取的是overcommit還是非overcommit佇列的,只是蘋果暫時不想讓呼叫罷了


### 七、那如果把一個並行佇列依附於一個overcommit佇列,是不是可以建立無數個執行緒?想想就很激動


測試結果為64個,看來蘋果對依附於'overcommit佇列'的並行佇列還是有限制的,依然限制為64個執行緒。


### 八、那我如果兩個並行佇列依附於兩個優先順序的overcommit佇列會出現什麼呢?


    dispatch_set_target_queue(self.queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, -1));
    dispatch_set_target_queue(self.queue2, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, -1));
   
    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue, ^{
            self.count++;
            NSLog(@"thread :%@  count %ld", [NSThread currentThread] ,self.count);
        });
    }
    


    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue2, ^{
            self.count++;
            NSLog(@"queue2 thread :%@  count %ld", [NSThread currentThread] ,self.count);
        });
    }


經測試,系統並沒有建立128個執行緒,而依然是64個,並且並不是優先輸出依附於高優先順序的並行佇列,而是各個佇列的輸出了4000多個輪流幾次輸出完畢。(他那兩個預設優先順序佇列也是輪流4000多)


說明當並行佇列依附於overcommit佇列時系統會轉交給DEFAULT優先順序的非overcommit佇列。


### 九、兩個同級別並行佇列會怎麼分配執行緒


    int sleepTime = 0/1000/10000/100000;
    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue, ^{
            self.count++;
            usleep(sleepTime);
            NSLog(@"thread :%@  count %ld", [NSThread currentThread] ,self.count);
        });
    }
    


    for (int i = 0; i < taskCount; i++) {
        dispatch_async(self.queue2, ^{
            self.count++;
            usleep(sleepTime);


            NSLog(@"queue2 thread :%@  count %ld", [NSThread currentThread] ,self.count);
        });
    }


無認是否sleep(),以及休眠的時間是多少都是會先執行self.queuer 4000多個任務,再執行self.queue2的4000多個任務,以次輪換。說明對於對於依附於同一佇列的不同佇列,也會有類似系統對執行緒排程,分配時間片一樣來排程,只是所依據的不再是時間,而是任務個數 


### 總結
1.gcd執行緒池,系統會建立64個執行緒給dispatch_get_global_queue獲取的4個並行佇列,當各優先順序都有任務時優先保證高優先順序的;如果序列佇列依附的是系統的並行佇列,則優先順序最高。
2.如果自己再建立序列佇列,系統會在64個執行緒基礎上再建立執行緒給序列佇列。
3.dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,1)
flags處開參傳入非0會獲取到overcommit佇列
4.如果設定並行佇列依附於overcommit佇列,系統會轉交給DISPATCH_QUEUE_PRIORITY_DEFAULT
5.對於依附於同一佇列的不同佇列,也會有類似系統對執行緒排程,分配時間片一樣來排程,只是所依據的不再是時間,而是任務個數 。不以時間而以任務個數肯定也是為了提高效率


系統為序列佇列單獨建立執行緒應該是考慮到:
1.序列佇列如果不單獨建立,很容易被執行更早的並行列隊搶佔完執行緒,導致並行佇列只能等待。
2.就算是搶到一個執行緒,執行完一個任務,下一個任務也不一定能搶到,這樣序列佇列就直接成悲劇了,只能執行一個任務,等一會,再執行一個。
###其他
1.以後有時間再測試建立10000個序列佇列,看系統會建立幾個執行緒,上限會是多少
2.到底為4000多多個少,這個需要再查原始碼了。

相關推薦

使用GCD處理幾執行之間的依賴關係。

根據執行結果可以看出,當主執行緒執行的時候,然而其他兩個任務中並沒有真正的完成,因為另外兩個任務中嵌套了子任務,那問題來了,其他兩個任務還沒有完成就執行主執行緒,但是我們需要的是其他兩個任務完成才需要執行主執行緒,別急,group給我們提供了dispatch_group_enter()與dispatch_g

你真的建立一個執行嗎?

在文章開始之前先看一個問題,下圖幾種建立執行緒方式分別是什麼,它們之間的區別和聯絡是什麼? 如果可以輕鬆回答,那麼本文對你來說過於基礎,不用往下看啦,如果還有所迷惑,那就和Nauyus一起復習下建立執行緒的幾種方式吧! 如何建立一個執行緒 Java執行緒類也是一個Object類,它的例項都繼承自java.

GCD建立多少執行

關於GCD佇列,系統佇列編號有11個,1為主佇列,2為管理佇列,3保留;4-11為8個全域性佇列,優先順序分別為LOW、DEFAULT、HIGH 和 BACKGROUND,4個佇列overcommit為YES,4個為NO; 如果為overcommit佇列,有新任務就會重新開

linux——pthread_create()到底可以建立多少執行

pthread_create()到底可以建立多少個執行緒? 今天在檢視pthread_create()函式的使用方法時,比較好奇它到底可以建立多少個執行緒呢?下面就來測試一番,以下是測試過程。 #include <pthread.h> #include <st

java併發:Executors可以建立的三執行

Executors.newSingleThreadExecutor();  建立一個單執行緒池,裡面維護了一個佇列.如果在執行過程中出現異常而終止.那麼下個任務將會建立一個新的執行緒. Executors.newCachedThreadPool(); 建立一個無邊界執行緒池.如

python中多執行開啟的兩種方式(內含有event的應用,即安全的機制,類似於java的等待喚醒機制,不出現多執行之間的錯亂問題)

 event是類似於java中的等待喚醒機制,具體方法參照上一篇CSDN 下面來介紹開啟執行緒的第一種方式 #Filename:threading1.py #開啟執行緒的第一種方式 import threading import time event=threadin

執行同時呼叫一個函式出現什麼情況?

from: https://www.cnblogs.com/silentNight/p/5468805.html 最近在研究多執行緒,然後突然想到如果兩個執行緒同時訪問一個函式的話,要不要加鎖呢,加鎖怎麼加,不加又怎樣這樣的問題..然後去網上找了些帖子學習學習......

python 建立執行並啟動

建立多個執行緒並啟動這些執行緒          th_num : 15 th_num = conf["crawl_threads"] self._thread_list = [] self.

建立執行、資料共享問題分析

Join 多個執行緒執行順序是亂的,跟作業系統內部對執行緒的排程機制有關。 主執行緒等待子執行緒執行完畢後才執行 void myprint(int item) { cout << "執行緒編號" << item << endl; } int main

JVM中可以建立多少執行

在JVM中,執行緒數量的多少與堆記憶體、棧記憶體的大小有著直接的關係,只不過棧記憶體更加明顯一些。在作業系統中,一個程序的記憶體大小是有限制的,這個限制稱為地址空間,比如32位的Windows作業系統最大的地址空間約為2G多一點,作業系統會將程序記憶體的大小控制在最大地址空間以內。下面是

建立執行、資料共享問題

目錄 1.建立和等待多個執行緒 2.資料共享問題分析 2.1 只讀資料 2.2 有讀有寫: 3.共享資料的保護案例程式碼 1.建立和等待多個執行緒 a)多個執行緒執行順序是亂的,跟作業系統內部對執行緒的執行排程機制有關; b)主執行緒等待所有子執行緒執行結束,

關於Spring容器中定時器到時執行出現兩執行同時執行的問題

最近公司有一個小需求,是需要定時去從某一個視訊供應商下載視訊檔案,問題很簡單,直接使用quartz,編寫相應的定時器程式碼,同時配置相應的定時器時間,但是在定時執行之後會出現兩個執行緒同時執行定時任務的問題,並且這兩個執行緒併發執行,從而一直影響到視訊檔案下載。

自定義類MyThread 實現Runnable介面,主函式建立5執行,自定義執行類的建構函式輸出 建立執行X

package com.heima.gu; import java.util.HashMap; public class Test01 { /**自定義類MyThread 實現Runnabl

iOS 中使用GCD怎麼讓兩執行執行完結束後再去執行另一個執行

//利用GCD並行多個執行緒並且等待所有執行緒結束之後再執行其它任務 dispatch_group_t group = dispatch_group_create(); dispatch_group_

Linux下一個程序究竟有多少執行

最近,在做一個關於聊天伺服器的專案,其中遇到了一個問題,那就是一個程序可以產生多少個執行緒呢? 開始各種想象,會和不同平臺,不同系統相關,網上很多大佬說是1024個,也有256個。 與其無端猜測,不如動手測試一下。在Linux32位平臺,進行測試。 1 #include

面試問我,建立多少執行合適?我該怎麼說

| **如果好看,請給個贊** > - 你有一個思想,我有一個思想,我們交換後,一個人就有兩個思想 > > - If you can NOT explain it simply, you do NOT understand it well enough 現陸續將Demo程式碼和技術文

Java 建立執行

1、繼承java.lang.Thread方式 執行start方法:MyThread的run就會被執行 程式碼片段: import java.util.Scanner; public class Main { public static void main(String[] a

筆記:Java實現三執行A B C,BC執行執行完再執行A線

final Lock lc = new ReentrantLock(); .. run() { lc.lock(); ... lc.unlock(); } 可能開啟方式不對吧,沒實現! 改用join() 可以實現(BC與A以單執行緒模式執行),程式碼如下: package

beginthreadex()函式在建立執行傳入回撥函式時,好像只能傳入全域性函式或類的靜態成員函式,請問能不能傳入類的成員函式呢(非靜態)?

C++類成員函式直接作為執行緒回撥函式2009年06月01日 星期一 17:01我以前寫執行緒時要麼老老實實照著宣告寫,要麼使用C++類的靜態成員函式來作為回撥函式,經常會因為執行緒程式碼而破壞封裝.之前雖然知道類成員函式的展開形式,但從沒想過利用過它,昨天看深入ATL時無意中學

Python建立執行任務並獲取每個執行返回值

轉自:https://www.cnblogs.com/bethansy/p/7965820.html 1.程序和執行緒     (1)程序是一個執行中的程式。每個程序都擁有自己的地址空間、記憶體、資料棧以及其他用於跟蹤執行的輔助資料。程序也可以派生新的程序來執行其他任務,