線程基礎相關

轉載自:http://www.cnblogs.com/yjg2014/p/yjg.html


IOS多線程知識總結/隊列概念/GCD/主隊列/並行隊列/全局隊列/主隊列/串行隊列/同步任務/異步任務區別(附代碼)

2014-04-25 14:37 by JG2014, 586 閱讀, 0 評論, 收藏編輯

 進程:正在進行中的程序被稱爲進程,負責程序運行的內存分配;每一個進程都有自己獨立的虛擬內存空間

 線程:線程是進程中一個獨立的執行路徑(控制單元);一個進程中至少包含一條線程,即主線程

 

 隊列 dispatch_queue_t,隊列名稱在調試時輔助,無論什麼隊列和任務,線程的創建和回收不需要程序員操作,有隊列負責。

   串行隊列:隊列中的任務只會順序執行(類似跑步)

        dispatch_queue_t q = dispatch_queue_create(“....”, DISPATCH_QUEUE_SERIAL);

 

   並行隊列:隊列中的任務通常會併發執行(類似賽跑)

        dispatch_queue_t q = dispatch_queue_create("......", DISPATCH_QUEUE_CONCURRENT);

 

   全局隊列:是系統的,直接拿過來(GET)用就可以;與並行隊列類似,但調試時,無法確認操作所在隊列

        dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

 

   主隊列:每一個應用程序對應唯一一個主隊列,直接GET即可;在多線程開發中,使用主隊列更新UI

        dispatch_queue_t q = dispatch_get_main_queue();

 

 操作

   dispatch_async 異步操作,會併發執行,無法確定任務的執行順序;

   dispatch_sync 同步操作,會依次順序執行,能夠決定任務的執行順序;

 

 串行隊列同步:操作不會新建線程、操作順序執行

 串行隊列異步:操作需要一個子線程,會新建線程、線程的創建和回收不需要程序員參與,操作順序執行,最安全的選擇

 

 

 並行隊列同步:操作不會新建線程、操作順序執行

 

 並行隊列異步:操作會新建多個線程(有多少任務,就開N個線程執行)、操作無序執行;隊列前如果有其他任務,會等待前面的任務完成之後再執行;場景:既不影響主線程,又不需要順序執行的操作!

 

 

 

 全局隊列異步:操作會新建多個線程、操作無序執行,隊列前如果有其他任務,會等待前面的任務完成之後再執行

 

 全局隊列同步:操作不會新建線程、操作順序執行

 

 

 

 主隊列異步:操作都應該在主線程上順序執行的,不存在異步的概念

 

 主隊列同步:如果把主線程中的操作看成一個大的Block,那麼除非主線程被用戶殺掉,否則永遠不會結束;主隊列中添加的同步操作永遠不會被執行,會死鎖

 

 

 不同隊列嵌套dispathch_sync(同步)任務的結果

 // 1.全局隊列,都在主線程上執行,不會死鎖 DISPATCH_QUEUE_PRIORITY_DEFAULT

 

 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

 

 // 2.並行隊列,都在主線程上執行,不會死鎖 DISPATCH_QUEUE_CONCURRENT

 

 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);

 

 // 3.串行隊列,會死鎖,但是會執行嵌套同步操作之前的代碼 DISPATCH_QUEUE_SERIAL

 

 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);

 

 // 4.主隊列,直接死鎖 dispatch_get_main_queue();

 

 dispatch_queue_t q = dispatch_get_main_queue();

 

 dispatch_sync(q, ^{

 

 NSLog(@"同步任務 %@", [NSThread currentThread]);

 

 dispatch_sync(q, ^{

 

 NSLog(@"同步任務 %@", [NSThread currentThread]);

 

 });

 

 });

 

 

 

 dispatch_sync同步應用場景

 

 阻塞並行隊列的執行,要求某一操作執行後再進行後續操作,如用戶登錄

 確保塊代碼之外的局部變量確實被修改

 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);

 

 __block BOOL logon = NO;

 

 dispatch_sync(q, ^{

 

 NSLog(@"模擬耗時操作 %@", [NSThread currentThread]);

 

 [NSThread sleepForTimeInterval:2.0f];

 

 NSLog(@"模擬耗時完成 %@", [NSThread currentThread]);

 

 logon = YES;

 

 });

 

 

 

 dispatch_async(q, ^{

 

 NSLog(@"登錄完成的處理 %@", [NSThread currentThread]);

 

 });

 

 

 

 ios三種多線程技術:

   1.NSThread

     (1)使用NSThread對象建立一個線程非常方便

     (2)但是!要使用NSThread管理多個線程非常困難,不推薦使用

     (3)技巧!使用[NSThread currentThread]跟蹤任務所在線程,適用於這三種技術

   2.NSOperation/NSOperationQueue

     (1)是使用GCD實現的一套Objective-CAPI

     (2)是面向對象的線程技術

     (3)提供了一些在GCD中不容易實現的特性,如:限制最大併發數量、操作之間的依賴關係

   3.GCD —— Grand Central Dispatch

     (1)是基於C語言的底層API

     (2)Block定義任務,使用起來非常靈活便捷

     (3)提供了更多的控制能力以及操作隊列中所不能使用的底層函數

 

 1---- 隊列和線程的區別:

 

 隊列:是管理線程的,相當於線程池,能管理線程什麼時候執行。

 

 隊列分爲串行隊列和並行隊列等

 

 串行隊列:隊列中的線程按順序執行(不會同時執行)

 

 並行隊列:隊列中的線程會併發執行,可能會有一個疑問,隊列不是先進先出嗎,如果後面的任務執行完了,怎麼出去的了。這裏需要強調下,任務執行完畢了,不一定出隊列。只有前面的任務執行完了,纔會出隊列。

 

 2----- 主線程隊列和GCD創建的隊列也是有區別的。

 

 主線程隊列和GCD創建的隊列是不同的。在GCD中創建的隊列優先級沒有主隊列高,所以在GCD中的串行隊列開啓同步任務裏面沒有嵌套任務是不會阻塞主線程,只有一種可能導致死鎖,就是串行隊列裏,嵌套開啓任務,有可能會導致死鎖。

 

 主線程隊列中不能開啓同步,會阻塞主線程。只能開啓異步任務,開啓異步任務也不會開啓新的線程,只是降低異步任務的優先級,讓cpu空閒的時候纔去調用。而同步任務,會搶佔主線程的資源,會造成死鎖。

 

 3----- 線程:裏面有非常多的任務(同步,異步)

 

 同步與異步的區別:

 

 同步任務優先級高,在線程中有執行順序,不會開啓新的線程。

 

 異步任務優先級低,在線程中執行沒有順序,看cpu閒不閒。在主隊列中不會開啓新的線程,其他隊列會開啓新的線程。

 

 4----主線程隊列注意:

 

 下面代碼執行順序

 

 1111

 

 2222

 

 主隊列異步 <NSThread: 0x8e12690>{name = (null), num = 1}

 

 在主隊列開啓異步任務,不會開啓新的線程而是依然在主線程中執行代碼塊中的代碼。爲什麼不會阻塞線程?

 

 > 主隊列開啓異步任務,雖然不會開啓新的線程,但是他會把異步任務降低優先級,等閒着的時候,就會在主線程上執行異步任務。

 

 在主隊列開啓同步任務,爲什麼會阻塞線程?

 

 > 在主隊列開啓同步任務,因爲主隊列是串行隊列,裏面的線程是有順序的,先執行完一個線程才執行下一個線程,而主隊列始終就只有一個主線程,主線程是不會執行完畢的,因爲他是無限循環的,除非關閉應用程序。因此在主線程開啓一個同步任務,同步任務會想搶佔執行的資源,而主線程任務一直在執行某些操作,不肯放手。兩個的優先級都很高,最終導致死鎖,阻塞線程了。

 

 

 

 /*

 

 1.主隊列

 

 */

 

- (void)main_queue_deadlock

 

{

    

    dispatch_queue_t q = dispatch_get_main_queue();

    

    NSLog(@"1111");

    

    dispatch_async(q, ^{

        

        NSLog(@"主隊列異步任務 %@", [NSThread currentThread]);

        

    });

    

    NSLog(@"2222");

    

    // 下面會造成線程死鎖

    

    //    dispatch_sync(q, ^{

    

    //        NSLog(@"主隊列同步 %@", [NSThread currentThread]);

    

    //    });

    

}

 

 

 

/**

 

 *  2.並行隊列裏開啓同步任務是有執行順序的,只有異步纔沒有順序

 

 */

 

- (void)concurrent_queue

 

{

    

    dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo"DISPATCH_QUEUE_CONCURRENT);

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@1111111", [NSThread currentThread]);

        

        

        

        dispatch_sync(q, ^{

            

            NSLog(@"同步任務 %@2222222", [NSThread currentThread]);

            

        });

        

        dispatch_sync(q, ^{

            

            NSLog(@"同步任務 %@333333", [NSThread currentThread]);

            

        });

        

    });

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@444444", [NSThread currentThread]);

        

    });

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@555555", [NSThread currentThread]);

        

    });

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@666666", [NSThread currentThread]);

        

    });

    

}

 

 

 

/**

 

 *  3.串行隊列開啓異步任務,是有順序的

 

 */

 

- (void)serial_queue

 

{

    

    dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo"DISPATCH_QUEUE_SERIAL);

    

    

    

    dispatch_async(q, ^{

        

        NSLog(@"異步任務 %@1111111", [NSThread currentThread]);

        

    });

    

    dispatch_async(q, ^{

        

        NSLog(@"異步任務 %@22222", [NSThread currentThread]);

        

    });

    

    dispatch_async(q, ^{

        

        NSLog(@"異步任務 %@3333", [NSThread currentThread]);

        

    });

    

    dispatch_async(q, ^{

        

        NSLog(@"異步任務 %@44444", [NSThread currentThread]);

        

    });

    

}

 

 

 

/**

 

 *  4.1.串行隊列開啓異步任務後嵌套同步任務造成死鎖

 

 */

 

- (void)serial_queue_deadlock2

 

{

    

    dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo"DISPATCH_QUEUE_SERIAL);

    

    dispatch_async(q, ^{

        

        NSLog(@"異步任務 %@", [NSThread currentThread]);

        

        // 下面開啓同步造成死鎖:因爲串行隊列中線程是有執行順序的,需要等上面開啓的異步任務執行完畢,纔會執行下面開啓的同步任務。而上面的異步任務還沒執行完,要到下面的大括號纔算執行完畢,而下面的同步任務已經在搶佔資源了,就會發生死鎖。

        

        dispatch_sync(q, ^{

            

            NSLog(@"同步任務 %@", [NSThread currentThread]);

            

        });

        

    });

    

}

 

 

 

/**

 

 *  4.2.串行隊列開啓同步任務後嵌套同步任務造成死鎖

 

 */

 

- (void)serial_queue_deadlock1

 

{

    

    dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo"DISPATCH_QUEUE_SERIAL);

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@", [NSThread currentThread]);

        

        // 下面開啓同步造成死鎖:因爲串行隊列中線程是有執行順序的,需要等上面開啓的同步任務執行完畢,纔會執行下面開啓的同步任務。而上面的同步任務還沒執行完,要到下面的大括號纔算執行完畢,而下面的同步任務已經在搶佔資源了,就會發生死鎖。

        

        dispatch_sync(q, ^{

            

            NSLog(@"同步任務 %@", [NSThread currentThread]);

            

        });

        

        

        

    });

    

    NSLog(@"同步任務 %@", [NSThread currentThread]);

    

}

 

 

 

/**

 

 *  4.3.串行隊列開啓同步任務後嵌套異步任務不造成死鎖

 

 */

 

- (void)serial_queue1

 

{

    

    dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo"DISPATCH_QUEUE_SERIAL);

    

    dispatch_sync(q, ^{

        

        NSLog(@"同步任務 %@", [NSThread currentThread]);

        

        

        

        // 開啓異步,就會開啓一個新的線程,不會阻塞線程

        

        dispatch_async(q, ^{

            

            NSLog(@"異步任務 %@", [NSThread currentThread]);

            

        });

        

        

        

    });

    

    NSLog(@"同步任務 %@", [NSThread currentThread]);

    

}

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章