ios線程和GCD和隊列同步異步的關係

一、什麼是進程?ios

  進程是指在系統中正在運行的一個應用程序。好比同時打開QQ、Xcode,系統就會分別啓動2個進程。截圖安全

  

二、什麼是線程?多線程

  1)、一個進程要想執行任務,必須得有線程(每個進程至少要有一條線程)併發

  2)、線程是進程的基本執行單元,一個進程(程序)的全部任務都在線程中執行異步

  3)、一個線程中任務的執行是串行的。即若是要在1個線程中執行多個任務,那麼只能一個一個的按順序執行這些任務async

三、什麼是多線程?ide

  1)、一個線程中能夠開啓多條線程,每條線程能夠並行執行不一樣的任務。好比同時開啓三條線程分別下載3個文件函數

  2)、同一時間,CPU只能處理一條線程,只有一條線程在工做(執行)性能

  3)、多線程併發(同時)執行,實際上是CPU快速的在多線程之間調度(切換)測試

  4)、若是cpu調度線程的時間足夠快,就形成了多線程併發執行的假象

  5)、若是線程很是很是多,那麼會發生什麼狀況呢?

    可能致使cpu在N條線程之間調度,消耗大量的cpu資源,進而致使每條線程被調度執行的頻次會下降(線程的執行效率下降)

  6)、多線程的優勢:能適當提升程序的執行效率;能適當提升資源利用率(cpu、內存利用率)

  7)、多線程的缺點:

    開啓線程須要佔用必定的內存空間(默認狀況下,主線程佔用1M,子線程佔用512KB),若是開啓大量的線程,會佔用大量的內存空間,下降程序的性能;

    線程越多,cpu在調度線程上的開銷就越大;

    程序設計更加複雜:好比線程之間的通訊、多線程的數據共享

四、什麼是主線程

  1)、一個ios程序運行後,默認會開啓一條線程,稱爲」主線程「或」UI線程「

  2)、主線程的做用:

    顯示/刷新UI界面;

    處理UI事件(好比點擊事件、滾動事件、拖拽事件等)

  3)、主線程的使用注意:

    別將比較耗時的操做放到主線程中;耗時操做會卡住主線程,嚴重影響UI的流暢度,給用戶一種」卡「的壞體驗;

    因此通常將耗時操做放在子線程(後臺線程、非主線程)

五、ios中多線程的實現方案:

  

 六、NSThread

  1)一個NSThread對象就表明一條線程

  2)建立、啓動線程:

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(testThread) object:nil];

    [thread start];

  3)、主線程相關用法:

    + (NSThread *)mainThread;  //獲取主線程

    - (BOOL)isMainThread;    //是否爲主線程

    + (BOOL)isMainThread;    //是否爲主線程

  4)、獲取當前線程: NSThread *current = [NSThread currentThread];

  5)、線程的調度優先級

    + (double)threadPriority;

    + (BOOL)setThreadPriority:(double)p;

    - (double)threadPriority;

    - (BOOL)setThreadPriority:(double)p;

    調度優先級的取值範圍是0.0 ~ 1.0, 默認是0.5, 值越大,優先級越高

  6)、線程的名字:- (void)setName: (NSString *)n;   - (NSString *)name;

  7)、另一種建立線程方法:建立線程後啓動線程:

    [NSThread detachNewThreadSelector:@selector(testThread) toTarget:self withObject:nil];

  8)、第三種建立線程方式:隱式建立並啓動線程:

    [self performSelectorInBackground:@selector(testThread) withObject:nil];

  9) 、後面2中建立線程方式的優缺點:

    優勢:簡單快捷

    缺點:沒法對線程進行更詳細的設置 

  10)、阻塞(暫停)線程:

    + (void)sleepUnitilDate:(NSDate *)date; //睡眠到date這個時間上

    + (void)sleepForTimeInterval:(NSTimeInterval)seconds;  //睡眠seconds秒

    調用這兩個方法中任一方法,當前線程會睡眠(暫停)所設置的時間後,纔會執行後面的操做

  11)、強制中止線程,讓當前線程提早結束它的生命:+ (void)exit; 

 七、多線程安全問題 - 互斥鎖

  1)、互斥鎖使用方式:@synchronized(所對象) { //須要鎖定的代碼 } ;    // 線程同步:多條線程按順序地執行任務

  2)、互斥鎖的優缺點:

    優勢:能有效防止因多線程搶奪同一資源形成的數據安全問題;

    缺點:須要消耗大量的CPU資源

八、原子和非原子屬性

  OC在定義屬性時有nonatomic和atomic兩種選擇

  atomic : 院子屬性,爲setter方法加鎖(默認就是atomic)

  nonatomic:非原子屬性,不會位setter方法加鎖

  ---------------- nontomic 和 atomic對比 -------

  atomic :線程安全,須要消耗大量的資源;

  nonatomic : 非線程安全,適合內存曉得移動設備

  ------ 對於設置屬性原子和非原子性的建議 --- 

  a、全部屬性都聲明位nontomic; 

  b、儘可能避免多線程搶奪同一塊資源;

  c、儘可能將加鎖、資源搶奪的業務邏輯交給服務端處理,減少移動客戶端的壓力。

九、線程間通訊

  在1個線程中,線程每每不是孤立存在的,多個線程之間須要常常進行通訊:好比說一個線程傳遞數據給另外一個線程,又或者在一個線程中執行完成特定任務後,轉到另外一個線程繼續執行任務。

  線程間通訊經常使用方法:

  - (void)performSelectorOnMainThread:(SEL)aSelectorWithObject:(id)arg waitUntilDone:(BOOL)wait; //傳遞數據到主線程

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; //傳遞數據到另外一個線程

 

十、GCD

  1)、GCD,全稱是Grand Central Dispatch,偉大的中央調度器。純C語言,提供了很是多強大的函數

  2)、GCD的優點:

    GCD是蘋果公司位多核的並行運算提出的解決方案;會自動利用更多的CPU內核;

    會自動管理線程的生命週期(建立線程、調度任務、銷燬線程)

  3)、GCD中2個核心概念:任務和隊列。任務指執行什麼操做,隊列是用來存聽任務。

    GCD的使用步驟:

      a、定製任務。肯定想作的事;    

      b、將任務添加到隊列中。GCD會自動將隊列中的任務取出,放到對應的線程中執行 ;任務的取出遵循隊列的FIFO原則:先進先出。

    GCD執行任務函數:

      用同步的方式執行任務:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);   // queue指隊列   ;  block指任務

      用異步的方式執行任務:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

      同步和異步的區別:同步只能在當前的線程中執行任務,不具有開啓新線程的能力; 異步能夠在新的線程中執行任務,具有開啓新線程的能力;

  4)、隊列的類型:主要分爲併發隊列和串行隊列

    併發隊列:Concurrent Dispatch Queue, 可讓多個任務併發(同時)執行(自動開啓多個線程同時執行任務);

         併發功能只有在異步(dispatch_async)函數下才有效

    串行隊列:Serial Dispatch Queue, 讓任務一個接着一個地執行(一個任務執行完畢後,再執行下一個任務)

    

    並行隊列:

    GCD默認已經提供了全局的併發隊列,供整個應用使用,不須要手動建立;

    使用dispatch_get_global_queue函數得到全局的併發隊列;

    dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,  unsigned long flags);  //priority指隊列的優先級, flags參數暫時無用,用0便可

    示例:dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,  0); //得到全局併發隊列  

    全局併發隊列的優先級:

    #define DISPATCH_QUEUE_PRIORITY_HIGH  2//高

    #define DISPATCH_QUEUE_PRIORITY_DEFAULT  0//默認(中)

    #define DISPATCH_QUEUE_PRIORITY_LOW (-2)  //低

    #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  //後臺

 

    串行隊列:

    使用dispatch_queue_create函數建立一個串行隊列

    dispatch_queue_create(const char *lable, dispatch_queue_attr_t attr); //lable參數指隊列名稱;attr參數指隊列屬性,通常用NULL便可

    另外可使用主隊列:dispatch_get_main_queue(),主隊列是GCD自帶的一種特殊的串行隊列;放在主隊列中的任務,都會放到主線程中執行

 

-----------------------------------------------------

線程和隊列、異步同步函數的關係?

一、一個應用程序表示開啓了一個進程

二、一個進程至少有一個線程,即至少有一個主線程,也能夠開啓多條線程

三、一個線程中能夠有多個隊列,每一個隊列中能夠執行多個任務

四、在線程中執行任務的順序能夠是按順序來執行,也能夠用不按順序來執行。即表現爲串行和並行

五、那異步和同步函數的做用在哪裏?

     是否開啓多條線程,而後執行的隊列(任務)是否按順序仍是不按順序執行,都須要異步和同步函數的配合才能實現!

    並行和串行隊列,與異步同步函數的排列組合有以下這些:

    a、並行隊列 + 異步函數 開啓多條線程,不按順序執行任務;

    b、串行隊列 + 異步函數 開啓一條新線程,按順序執行任務;

    c、主隊列 + 異步函數不開啓新線程,按順序執行任務

 

    d、並行隊列 + 同步函數不開啓新線程,按順序執行任務;

    e、串行隊列 + 同步函數不開啓新線程,按順序執行任務;

    f、主隊列 + 同步函數會出現卡死現象!緣由:循環等待,主隊列的東西要等主線程執行完,又不能開線程,

因此下面的任務要等上面的任務執行完,而後卡死

 

舉例說明:

1、並行隊列 + 異步函數:開啓多條線程,不按順序執行任務 (全局隊列+異步函數效果同樣)

dispatch_queue_t q1 = dispatch_queue_create("mulQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 100; i++){
        dispatch_async(q1, ^{
            NSLog(@"並行+異步,i=%d, currentThread: %@", i, [NSThread currentThread]);
        });
    }
    NSLog(@"並行隊列+異步函數測試執行 end....");
    /*
     並行隊列+異步函數測試執行 end....
     並行+異步,i=1, currentThread: <NSThread: 0x60000026ab80>{number = 5, name = (null)}
     並行+異步,i=0, currentThread: <NSThread: 0x600000269b00>{number = 3, name = (null)}
     並行+異步,i=4, currentThread: <NSThread: 0x60000026ea80>{number = 7, name = (null)}
     並行+異步,i=3, currentThread: <NSThread: 0x600000269bc0>{number = 6, name = (null)}
     並行+異步,i=5, currentThread: <NSThread: 0x60800026d8c0>{number = 8, name = (null)}
     ....
     並行+異步,i=97, currentThread: <NSThread: 0x600000272f80>{number = 49, name = (null)}
     並行+異步,i=99, currentThread: <NSThread: 0x600000273000>{number = 50, name = (null)}
     並行+異步,i=98, currentThread: <NSThread: 0x60000026ad40>{number = 11, name = (null)}
     */
View Code

 

2、並行 + 同步:不開啓線程,按順序執行,在主線程執行

dispatch_queue_t q2 = dispatch_queue_create("mulQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 100; i++){
        dispatch_sync(q2, ^{
            NSLog(@"並行+同步,i=%d, currentThread: %@", i, [NSThread currentThread]);
        });
    }
    NSLog(@"並行隊列+同步函數測試執行 end....");
    /*
     並行+同步,i=0, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     並行+同步,i=1, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     並行+同步,i=2, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     ....
     並行+同步,i=97, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     並行+同步,i=98, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     並行+同步,i=99, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
     並行隊列+同步函數測試執行 end....
     */
View Code

 

3、串行 + 異步:開啓一條新線程,按順序執行

dispatch_queue_t q3 = dispatch_queue_create("singleQueue", NULL);
    for (int i = 0; i < 100; i++){
        dispatch_async(q3, ^{
            NSLog(@"串行+異步,i=%d, currentThread: %@", i, [NSThread currentThread]);
        });
    }
    NSLog(@"串行隊列+異步函數測試執行 end....: %@", [NSThread currentThread]);
    /*
     串行+異步,i=0, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     串行隊列+異步函數測試執行 end....: <NSThread: 0x60800007b800>{number = 1, name = main}
     串行+異步,i=1, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     串行+異步,i=2, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     ....
     串行+異步,i=97, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     串行+異步,i=98, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     串行+異步,i=99, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
     */
View Code

 

4、主隊列 + 異步:不開啓新線程,按順序執行

dispatch_queue_t q4 = dispatch_get_main_queue();
    for (int i = 0; i < 100; i++){
        dispatch_async(q4, ^{
            NSLog(@"主隊列+異步,i=%d, currentThread: %@", i, [NSThread currentThread]);
        });
    }
    NSLog(@"主隊列+異步函數測試執行 end....: %@", [NSThread currentThread]);
    /*
     主隊列+異步函數測試執行 end....: <NSThread: 0x60000006fe00>{number = 1, name = main}
     主隊列+異步,i=0, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     主隊列+異步,i=1, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     主隊列+異步,i=2, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     ....
     主隊列+異步,i=97, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     主隊列+異步,i=98, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     主隊列+異步,i=99, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
     */
View Code
相關文章
相關標籤/搜索