ios多線程編程(NSThread)(NSOperation )(GCD)

1:首先簡單介紹什麼叫線程

  • 可併發執行的,擁有最小系統資源,共享進程資源的基本調度單位。
  • 共用堆,自有棧(官方資料說明iOS主線程棧大小爲1M,其它線程爲512K)。
  • 併發執行進度不可控,對非原子操作易造成狀態不一致,加鎖控制又有死鎖的風險。

2:IOS中的線程

  • iOS主線程(UI線程),我們的大部分業務邏輯代碼運行於主線程中。
  • 沒有特殊需求,不應引入線程增加程序複雜度。
  • 應用場景:邏輯執行時間過長,嚴重影響交互體驗(界面卡死)等。
  • IOS 多線程 有三種主要方法
    1)NSThread
    (2)NSOperation
    (3)GCD

    下面簡單介紹這三個方法 

    1.NSThread

        調用方法如下: 

        如函數需要輸入參數,可從object傳進去。
        (1) [NSThread detachNewThreadSelector:@selector(threadInMainMethod:) toTarget:self withObject:nil];
        (2) NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadInMainMethod:) object:nil];
     [myThread start]; 
        (3) [obj performSelectorInBackground:@selector(threadMe) withObject:nil];

    提個問題:如果某個ViewController裏運行了一個Thread,Thread還沒結束的時候,這個ViewController被Release了,結果會如何? 

    經過的的測試,Thread不結束,ViewController一直保留,不會執行dealloc方法。

    2.NSOperation  

    NSoperation也是多線程的一種,NSopertaion有2種形式
      (1) 併發執行
           併發執行你需要重載如下4個方法
         //執行任務主函數,線程運行的入口函數
        - (void)start 
           //是否允許併發,返回YES,允許併發,返回NO不允許。默認返回NO
        -(BOOL)isConcurrent 
        - (BOOL)isExecuting
         //是否已經完成,這個必須要重載,不然放在放在NSOperationQueue裏的NSOpertaion不能正常釋放。
       - (BOOL)isFinished
       
       比如TestNSOperation:NSoperaion 重載上述的4個方法,
       聲明一個NSOperationQueue, NSOperationQueue *queue = [[[NSOperationQueue alloc ] init] autorelease];
      [queue addOperation:testNSoperation];

      它會自動調用TestNSOperation裏的 start函數,如果需要多個NSOperation,你需要設置queue的一些屬性,如果多個NSOperation之間又依賴關係,也可以設置,具體可以參考API 文檔。 

    (2)非併發執行
      -(void)main
       只需要重載這個main方法就可以了。  

      3.GCD

      GCD很強大,我的使用經驗很少。但是scorpiozj 總結的比較全面(http://www.cnblogs.com/scorpiozj/archive/2011/07/25/2116459.html

      同時,這篇文章也介紹的比較詳細 http://www.cnblogs.com/vinceoniphone/archive/2011/04/07/2007968.html 

         官方教程

    GCD是和block緊密相連的,所以最好先了解下block(可以查看這裏).GCD是C level的函數,這意味着它也提供了C的函數指針作爲參數,方便了C程序員.

    下面首先來看GCD的使用:

    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

    async表明異步運行,block代表的是你要做的事情,queue則是你把任務交給誰來處理了.(除了async,還有sync,delay,本文以async爲例).

    之所以程序中會用到多線程是因爲程序往往會需要讀取數據,然後更新UI.爲了良好的用戶體驗,讀取數據的操作會傾向於在後臺運行,這樣以避免阻塞主線程.GCD裏就有三種queue來處理.

    1. Main queue:

      顧名思義,運行在主線程,由dispatch_get_main_queue獲得.和ui相關的就要使用Main Queue.

    2.Serial quque(private dispatch queue)

      每次運行一個任務,可以添加多個,執行次序FIFO(隊列,先進先出first input first out). 通常是指程序員生成的,比如:

    dispatch_queue_t myCustomQueue = dispatch_queue_create("example.MyCustomQueue", NULL);
    dispatch_async(myCustomQueue, ^{
        for (int abc=0;abc<100;abc++)
            {
                printf("1.Do some work here.\n");
            }
        });
    dispatch_async(myCustomQueue, ^{
        for (int abc=0;abc<100;abc++)
            {
                printf("2.Do some work here.\n");    
            }
        });
    dispatch_queue_t myCustomQueue2 = dispatch_queue_create("example.MyCustomQueue2", NULL);
    dispatch_async(myCustomQueue2, ^{
        for (int abc=0;abc<100;abc++)
            {
                printf("1. myCustomQueue2 Do some work here.\n");
            }
        });
    dispatch_async(myCustomQueue2, ^{
        for (int abc=0;abc<100;abc++)
            {
                printf("2. myCustomQueue2 Do some work here.\n");
            }
        });
    打印的結果必定會是 :然而,因爲myCustomQueue 和 myCustomQueue2 是在兩個隊列中,所以在隊列myCustomQueue中:
    “1.Do some work here.” 在 “2.Do some work here.” 之前,而在myCustomQueue2隊列中:“1. myCustomQueue2 
    Do some work here.”在“2. myCustomQueue2 Do some work here.”之前。而在myCustomQueue和myCustomQueue2
    之中的任務是沒有先後的。及不是併發的。
    

    3. Concurrent queue(global dispatch queue):

    可以同時運行多個任務,每個任務的啓動時間是按照加入queue的順序,結束的順序依賴各自的任務.使用dispatch_get_global_queue獲得.

    所以我們可以大致瞭解使用GCD的框架:

    dispatch_queue_t newThread = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(newThread,^{[self downloadImage:ImageURL]; 
    }); 小節:NSThread的方式或許能做更快的切換,因爲ARMv6或更高版本的處理器都提供了非常強大的線程切換機制。但是NSThread不會 採取多核的分派,因爲這個系統接口首先要保證的是用戶線程的可靠性。 而Grand Central Dispatch顯式地利用分派隊列來做多核 分派調度,因此如果是在多核處理器上的話用G_C_D更快。如果你的處理器是單核心的話,那麼可以使用切換更快的NSThread。

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