iOS 開發多線程 —— GCD,ios開發多線程gcd

來源:互聯網
上載者:User

iOS 開發多線程 —— GCD,ios開發多線程gcd

本文是根據文頂頂老師的部落格學習總結而來,如有不妥之處,還望指出。http://www.cnblogs.com/wendingding/p/3807716.html

一. 任務和隊列

GCD中有2個核心概念

(1)任務:執行什麼操作

(2)隊列:用來存放任務

 

GCD的使用就2個步驟

(1)定製任務

(2)確定想做的事情

 

將任務添加到隊列中,GCD會自動將隊列中的任務取出,放到對應的線程中執行

提示:任務的取出遵循隊列的FIFO原則:先進先出,後進後出

 

二. 執行任務

1. GCD中有2個用來執行任務的函數

說明:把右邊的參數(任務)提交給左邊的參數(隊列)進行執行。

(1)用同步的方式執行任務 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

參數說明:

queue:隊列

block:任務

 

(2)用非同步方式執行任務 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

2. 同步和非同步區別

同步:在當前線程中執行

非同步:在另一條線程中執行

 

三. 隊列

1. 隊列的類型

GCD的隊列可以分為2大類型

(1)並發隊列(Concurrent Dispatch Queue)

可以讓多個任務並發(同時)執行(自動開啟多個線程同時執行任務)並發功能只有在非同步(dispatch_async)函數下才有效

 

(2)串列隊列(Serial Dispatch Queue)

讓任務一個接著一個地執行(一個任務執行完畢後,再執行下一個任務)

 

2. 補充說明

有4個術語比較容易混淆:同步、非同步、並發、串列

同步和非同步決定了要不要開啟新的線程

同步:在當前線程中執行任務,不具備開啟新線程的能力

非同步:在新的線程中執行任務,具備開啟新線程的能力

 

並發和串列決定了任務的執行方式

並發:多個任務並發(同時)執行

串列:一個任務執行完畢後,再執行下一個任務

 

3. 串列隊列

GCD中獲得串列有2種途徑

(1)使用dispatch_queue_create函數建立串列隊列

dispatch_queue_t  dispatch_queue_create(const char *label,  dispatch_queue_attr_t attr); // 隊列名稱, 隊列屬性,一般用NULL即可

樣本:

dispatch_queue_t queue = dispatch_queue_create("wendingding", NULL); // 建立

dispatch_release(queue); // 非ARC需要釋放手動建立的隊列

 

(2)使用主隊列(跟主線程相關聯的隊列)

主隊列是GCD內建的一種特殊的串列隊列,放在主隊列中的任務,都會放到主線程中執行

使用dispatch_get_main_queue()獲得主隊列

樣本:

dispatch_queue_t queue = dispatch_get_main_queue();

 

4. 並發隊列

GCD預設已經提供了全域的並發隊列,供整個應用使用,不需要手動建立

使用dispatch_get_global_queue函數獲得全域的並發隊列

dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags); // 此參數暫時無用,用0即可

樣本:

這個參數是留給以後用的,暫時用不上,傳個0。

第一個參數為優先順序,這裡選擇預設的。擷取一個全域的預設優先順序的並發隊列。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 獲得全域並發隊列

 

常見的建立方式:

//用同步函數向串列隊列新增工作,不開闢新線程    dispatch_sync(dispatch_queue_create("syncqqq", NULL), ^{        NSLog(@"currentThread=%@",[NSThread currentThread]);    });    //currentThread=<NSThread: 0x17006bb00>{number = 1, name = main}            //用同步函數向並發隊列新增工作,不開闢新線程    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{       NSLog(@"currentThread=%@",[NSThread currentThread]);    });    //currentThread=<NSThread: 0x17006bb00>{number = 1, name = main}            //用非同步函數向串列隊列新增工作,開闢新線程(只開闢一條線程,任務串列執行)    dispatch_queue_t queue = dispatch_queue_create("www", NULL);    dispatch_async(queue, ^{        for (int i=0; i<10000; i++) {            NSLog(@"currentThread1=%@",[NSThread currentThread]);        }           });    dispatch_async(queue, ^{        NSLog(@"currentThread2=%@",[NSThread currentThread]);    });    //currentThread1=<NSThread: 0x17007c500>{number = 4, name = (null)}    //currentThread2=<NSThread: 0x17007c500>{number = 4, name = (null)}                //用非同步函數向並發隊列新增工作,開闢新線程(有多少任務開闢多少線程,任務並發執行)    dispatch_queue_t aqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_async(aqueue, ^{        for (int i=0; i<10000; i++) {            NSLog(@"currentThread3=%@",[NSThread currentThread]);        }           });    dispatch_async(aqueue, ^{        NSLog(@"currentThread4=%@",[NSThread currentThread]);    });

 

說明:同步函數不具備開啟線程的能力,無論是什麼隊列都不會開啟線程;非同步函數具備開啟線程的能力,開啟幾條線程由隊列決定(串列隊列只會開啟一條新的線程,並發隊列會開啟多條線程)。

同步函數

(1)並發隊列:不會開線程

(2)串列隊列:不會開線程

非同步函數

(1)並發隊列:能開啟N條線程

(2)串列隊列:開啟1條線程

 

常見用法:

1.從子線程回到主線程

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{       //在這執行一些耗時操作        dispatch_async(dispatch_get_main_queue(), ^{            //回到主線程進行操作        });            });

 

注意:

dispatch_sync(dispatch_get_main_queue(), ^{

        

    });

這種寫法是錯誤的,會造成程式崩潰.

 

2.延遲調用

(1)

[self performSelector:@selector(run) withObject:nil afterDelay:5.0];

注意:如果將

[self performSelector:@selector(run) withObject:nil afterDelay:5.0];放到子線程中,例如:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [self performSelector:@selector(run) withObject:nil afterDelay:5.0];

    });

這時候程式不會運行 run 方法。

正確寫法:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [self performSelector:@selector(run) withObject:nil afterDelay:5.0];

        [[NSRunLoop currentRunLoop] run];

    });

(2)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        //5秒後執行這裡的操作,可以選擇在哪個線程中執行,即:可以用dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 代替 dispatch_get_main_queue()

        

    });

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.