1.GCD.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (retain, nonatomic) IBOutlet UILabel *outletLabel1;
@property (retain, nonatomic) IBOutlet UILabel *outletLabel2;
@property (retain, nonatomic) IBOutlet UILabel *outletLabel3;
@property (retain, nonatomic) IBOutlet UILabel *outletLabel4;
- (IBAction)btnClick4:(UIButton *)sender;
- (IBAction)btnClick2:(UIButton *)sender;
- (IBAction)btnClick3:(UIButton *)sender;
- (IBAction)btnClick:(UIButton *)sender;
@end
2.GCD.m
/*
GCD(系統管理線程) 簡介
使用GCD你不需要編寫線程代碼,只需定義想要執行的任務,然後添加到適當的 dispatch queue (調度隊列)裡
GCD會負責建立線程和調度你的任務.系統直接提供線程管理,比應用實現更高效
基於C的執行自訂任務機制,dispatch queue 按先進先出的順序,串列或並發地執行任務.dispatch queue 分以下三種:
serial dispatch queue : 串列調度隊列,一次只執行一個任務,直到當前任務完成才開始出列並啟動下一個任務
主要用於對特定資源的同步訪問.雖然每個串列queue本身每次只能執行一個任務,但各個串列queue之間是並發執行的
concurrent dispatch queue: 也稱為 global dispatch queue, 並行調度隊列,並發執行一個或多個任務,但啟動順序仍是按照添加到
queue的順序啟動你不能建立並發dispatch queues, 只能使用系統已經定義好了的三個全域並發queues,
具體下面說到
main dispatch queue : 全域可用的串列 queue,在應用主線程中執行任務,比如用於重新整理UI介面
dispatch queue 相關的技術
Dispatch group : 用於監控一組block對象完成
Dispatch semaphore : 類似於傳統的 semaphore (訊號量)
Dispatch Source : 系統事件非同步處理機制
dispatch queue 中的 各個線程,可以通過queue的context指標來共用資料
*/
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
全域並發 Dispatch queue
1. 並發 dispatch queue 可以同時並發執行多個任務,不過並發 queue 仍然按照先進先出的順序啟動任務
2. 並發 queue 同時執行的任務數量會根據應用和系統動態變化,各個因素如:可用核心數量 其他進程正在執行的工作數量 其他串列dispatch queue 中的優先任務的數量等
3. 系統會給每個應用程式提供三個並發 dispatch queue,全域共用,三個queue的唯一區別在於優先順序不同
*/
- (IBAction)btnClick4:(UIButton *)sender {
/*
擷取全域並發 dispatch queue : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
第一個參數表示 queue 的優先順序,這裡擷取預設優先順序的那個queue,也可以擷取高/低優先順序的那個,把 DEFAULT 換成 HIGH 或 LOW 就行了
第二個參數表示 ?
*/
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//把一個block加入到全域並發調度隊列裡
dispatch_async(aQueue, ^(void) {
for (int i = 0; i < 1000; i++) {
//把block同步添加到主線程裡,這樣子,demo queue 就會暫停等這個block執行完成才繼續執行
dispatch_sync(dispatch_get_main_queue(), ^(void) {
NSString *text = [NSString stringWithFormat:@"%d", i];
self.outletLabel3.text = text;
});
}
});
//把另一個block加入到全域並發調度隊列裡.這個block和上面那個block會並發執行
dispatch_async(aQueue, ^(void){
for (int i = 0; i < 1000; i++) {
//把block同步添加到主線程裡,這樣子,demo queue 就會暫停等這個block執行完成才繼續執行
dispatch_sync(dispatch_get_main_queue(), ^(void) {
NSString *text = [NSString stringWithFormat:@"%d", i];
self.outletLabel4.text = text;
});
}
});
}
/*
串列 Dispatch queue
1. 串列 queue 每次只能執行一個任務,可以使用它來代替鎖,保護共用資源或可變的資料結構,串列queue確保任務按可預測的順序執行(這是比鎖好的地方)
2. 必須顯式建立和管理所有你使用的串列queue(數目任意)
*/
- (IBAction)btnClick2:(UIButton *)sender {
/*
使用 dispatch_queue_create() 方法來建立串列queue
第一個參數表示 queue 的名字, 第二個參數表示 queue 的一組屬性(保留給將來使用)
*/
dispatch_queue_t queue = dispatch_queue_create("demo queue", NULL);
/*
非同步調度和同步調度
非同步調度 dispatch_async : 把一個任務添加到某queue後就馬上離開,而不管任務在那個queue裡的執行狀態
同步調度 dispatch_sync : 把一個任務添加到某queue後,等這個任務完成,調用線程才繼續執行.尼瑪,坑爹啊
所以,非同步調度和同步調度的區別不在於被添加的任務怎樣執行,而在於調用線程是否等待任務執行完
*/
//把block非同步添加到上面建立的名為 demo queue 的調度隊列裡
dispatch_async(queue, ^(void){
for (int i = 0; i < 1000; i++) {
// sleep(1);
// printf("a%d\t",i);
//把block同步添加到主線程裡,這樣子,demo queue 就會暫停等這個block執行完成才繼續執行
dispatch_sync(dispatch_get_main_queue(), ^(void) {
NSString *text = [NSString stringWithFormat:@"%d", i];
self.outletLabel1.text = text;
// printf("b%d\n",i);
});
}
});
//因為 demo queue 是串列調度隊列,所以等上面那個block執行完,下面這個block才會開始
dispatch_async(queue, ^(void){
for (int i = 0; i < 1000; i++) {
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.outletLabel2.text = [NSString stringWithFormat:@"%d", i];
});
}
});
//xxxxx_create 的object對象要對應 xxxxx_release ?
dispatch_release(queue);
//這個迴圈都會卡螢幕~~~
// for (int i = 0; i < 100000; i++) {
// self.outletLabel1.text = [NSString stringWithFormat:@"%d", i];
// printf("%d\n", i);
// }
}
/*
dispatch_group 可以把一組task放到一個group裡,等group裡的所有task都執行完後再繼續運行
*/
- (IBAction)btnClick3:(UIButton *)sender {
//重設label2的text
self.outletLabel2.text = @"begin";
//擷取一個全域並發 調度隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//建立一個 dispatch group
dispatch_group_t group = dispatch_group_create();
//定義 task1
dispatch_block_t task1 = ^(void){
for (int i = 0; i < 300; i++) {
dispatch_sync(dispatch_get_main_queue(), ^(void){
self.outletLabel3.text = [NSString stringWithFormat:@"%d", i];
});
}
};
//定義task2
dispatch_block_t task2 = ^(void){
for (int i = 0; i < 300; i++) {
dispatch_sync(dispatch_get_main_queue(), ^(void){
self.outletLabel4.text = [NSString stringWithFormat:@"%d", i];
});
}
};
//把task1關聯到 queue 和group
dispatch_group_async(group, queue, task1);
//把task2關聯到 queue和group
dispatch_group_async(group, queue, task2);
//等group裡的task都執行完後執行notify方法裡的內容,相當於把wait方法及之後要執行的代碼合到一起了
dispatch_group_notify(group, dispatch_get_main_queue(), ^(void){
self.outletLabel2.text = @"done!";
});
//XXX_create建立,就需要對應的 XXX_release()
dispatch_release(group);
}
/*
dispatch source
*/
- (IBAction)btnClick:(UIButton *)sender {
}
- (void)dealloc {
[_outletLabel1 release];
[_outletLabel2 release];
[_outletLabel3 release];
[_outletLabel4 release];
[super dealloc];
}
@end