iOS開發實踐之多線程(GCD)

來源:互聯網
上載者:User

iOS開發實踐之多線程(GCD)
什麼是GCD:1、GCD是蘋果開發的一個多核編程的解決方案,和其它多線程技術方案相比,使用起來更加簡單和方便.
2、純C語言,提供了非常多強大的函數GCD的優勢:1、GCD是蘋果公司為多核的並行運算提出的解決方案
2、GCD會自動利用更多的CPU核心(比如雙核、四核)
3、GCD會自動管理線程的生命週期(建立線程、調度任務、銷毀線程)
4、程式員只需要告訴GCD想要執行什麼任務,不需要編寫任何線程管理代碼隊列和任務:

GCD中有2個核心概念

任務:執行什麼操作,用block來封裝任務。

隊列:用來存放任務。

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

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

隊列的類型

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

1、獲得全域的並發隊列

 //dispatch_queue_priority_t priority:隊列的優先順序 //unsigned long 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// 後台

串列隊列:讓任務一個接著一個地執行(一個任務執行完畢後,再執行下一個任務)。

1、使用dispatch_queue_create函數建立串列隊列

//const char *label:隊列名稱//dispatch_queue_attr_t attr:隊列屬性,一般用NULL即可dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);
dispatch_release(queue); // 非ARC需要釋放手動建立的隊列

2、使用主隊列(跟主線程相關聯的隊列),主隊列是GCD內建的一種特殊的串列隊列
放在主隊列中的任務,都會放到主線程中執行
使用dispatch_get_main_queue()獲得主隊列

dispatch_queue_t queue = dispatch_get_main_queue();

執行任務:

1、用同步的方式執行任務

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

同步和非同步區別:

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

2、非同步:可以在新的線程中執行任務,具備開啟新線程的能力。 dispatch_async

隊列和執行任務方式組合分析:

ps 特別注意:使用sync函數往當前串列隊列中新增工作,會卡住當前的串列隊列

/** * 非同步全域並發 * async並發隊列(最常用) * 會建立線程,一般同時開多條 * 並發執行 **/-(void)asyncGlobalQueue{    //擷取全域並發隊列    //dispatch_queue_priority_t priority:隊列的優先順序    //unsigned long flags:此參數暫時無用,用0即可    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        //將任務添加到全域隊列中去非同步執行    dispatch_async(queue, ^{        NSLog(@"------下載圖片1----%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"-----下載圖片2-----%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"----下載圖片3------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"-----下載圖片4----%@",[NSThread currentThread]);    });    }/** * 串列隊列(有時候會用) * 會建立線程,一般只開一條 * 串列執行,(一個任務執行完畢後再執行下一個任務) **/-(void)asyncSerialQueue{    //建立串列隊列    //const char *label:隊列名稱    //dispatch_queue_attr_t attr:隊列屬性,一般用NULL即可    dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);        //將任務添加到串列隊列中 非同步執行    dispatch_async(queue,^{        NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);    });    }/** * async --主隊列(很常用) **/-(void)asyncMainQueue{    //主隊列(添加到主隊列中的任務,都會自動放到主線程中去執行)    dispatch_queue_t queue = dispatch_get_main_queue();        //新增工作到主隊列中非同步執行    dispatch_async(queue, ^{        NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{        NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);    });        dispatch_async(queue, ^{       NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);    });    }/** * sync --主隊列(不能用,會卡死) **/-(void)syncMainQueue{    //主隊列(添加到主隊列中的任務,都會自動放到線程中去執行)    dispatch_queue_t queue = dispatch_get_main_queue();        //將任務添加到主隊列中同步執行    dispatch_sync(queue, ^{        NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{         NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{         NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{         NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{         NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);    });}/** *  sync --並發隊列 *  不會建立線程 *  串列執行(一個任務執行完畢後再執行下一個任務) *  並發隊列失去了並發的功能 **/-(void)syncGlobalQueue{    //擷取全域的並發隊列    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        //將任務添加到全域並發隊列中同步執行    dispatch_sync(queue, ^{        NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);    });}/** * sync --串列隊列 * 不會建立線程 * 串列執行(一個任務執行完畢後再執行下一個任務) **/-(void)syncSerialQueue{    //建立一個串列隊列    dispatch_queue_t queue = dispatch_queue_create("cn.xxx", NULL);        //將任務添加到串列隊列中同步執行    dispatch_sync(queue, ^{        NSLog(@"--------下載圖片1---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片2---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片3---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片4---------%@",[NSThread currentThread]);    });        dispatch_sync(queue, ^{        NSLog(@"--------下載圖片5---------%@",[NSThread currentThread]);    });}

一次性執行:

 //一次性執行 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{     //<#code to be executed once#> });
延時執行:
//延時執行(2秒)double delayInSeconds = 2;dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{    // <#code to be executed after a specified delay#>});

線程組:後台並發執行線程,等所有線程執行結束後再匯總執行結果

//1、擷取線程組dispatch_group_t group = dispatch_group_create();    //2、並存執行線程dispatch_group_async(group, queue, ^{    //並發執行線程一);ispatch_group_async(group, queue, ^{   //並發執行線程二});    //3、所有線程執行完成後調用dispatch_group_notify(group, queue, ^{   //匯總結果});
線程間通訊

從子線程回到主線程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執行耗時的非同步作業...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主線程,執行UI重新整理操作
});
});

例子:子線程下載圖片,下載後更新介面的imageView.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_async(queue, ^{        //子線程下載圖片        NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];        NSData *data = [NSData dataWithContentsOfURL:url];        UIImage *image = [UIImage imageWithData:data];                //回到主線程        dispatch_queue_t mainQueue = dispatch_get_main_queue();        dispatch_async(mainQueue, ^{            self.imageView.image = image;        });    });}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.