GCD程式設計
目錄
一、GCD的隊列dispatch_queue_t
1、簡介
2、建立
1)、create方法
2)、get系統方法
3、修改create方法建立的隊列優先級
二、GCD的使用方法
1、使用步驟
2、代碼示例
三、GCD的其他方法
1、dispatch_after-------------------------指定時間後追加
2、dispatch_group_t-----------------------處理組
3、dispatch_barrier_async-----------------queue中等待A執行後繼續queue中追加到其他
4、 dispatch_sync--------------------------同步
5、dispatch_apply-------------------------指定次數的重複追加
6、dispatch_suspend&dispatch_resume-------暫停和繼續
7、dispatch_semaphore_t-------------------設定計數點
8、dispatch_once_t------------------------隻執行一次
一、GCD的隊列dispatch_queue_t
1、簡介
dispatch_queue_t queue:執行處理的等待隊列可以将需要處理的代碼塊添加到這個隊列中
queue的分類:Serial順序 Concurrent并行
2、建立
有兩種方法,分别是create生成與get系統提供的
1)create queue:
dispatch_queue_create("", NULL)//第一個參數是queue的名字,第二個參數為NULL表示Serial順序,這個隻用于防止多對一的資料競争時
dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT)//第一個參數是queue的名字,第二個參數為DISPATCH_QUEUE_CONCURRENT表示Concurrent并行
dispatch_release(queue);//create的queue需要在結束使用後手動進行release
2)系統queue:分為Main主線程(也是一個Serial)和Global分線程(也是Concurrent)
Main:dispatch_queue_t queue = dispatch_get_main_queue();
Global://有四個優先級
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)//第一個參數為優先級,這裡為高優先級,第二個目前未使用,并且應該始終為0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)//第一個參數為優先級,這裡為預設優先級,第二個目前未使用,并且應該始終為0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)//第一個參數為優先級,這裡為低優先級,第二個目前未使用,并且應該始終為0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)//第一個參數為優先級,這裡為背景優先級,第二個目前未使用,并且應該始終為0
3、修改create方法建立的隊列優先級
create 建立的 queue 預設為 Global 的 DEFAULT 優先級,可以通過 dispatch_set_target_queue(originQueue, targetQueue); //進行修改,第一個參數為希望修改的queue,第二個參數為修改後的目标queue,且第一個queue必須為create建立的,不能使系統的Main或者Globalqueue。第二個queue應該是通過Global建立的某種優先級的queue
二、GCD的使用方法
1、使用步驟
first:使用create或者系統方法建立一個queue
second:使用dispatch_async(someQueue, ^{});執行多線程的block方法
third:在上面多線程的block相應位置調用dispatch_async(dispatch_get_main_queue(), ^{});回到主線程進行操作
fourth:如果queue時通過create建立的,使用dispatch_release(someQueue);進行釋放
2、代碼示例
dispatch_queue_t tempQueue = dispatch_queue_create("com.llz.gcd.temp", NULL);
dispatch_async(tempQueue,
^{
//do something
dispatch_async(dispatch_get_main_queue(),
^{
//do someting
});
});
dispatch_release(tempQueue);//因為是create出來的,是以需要release
三、GCD的其他方法
1、dispatch_after
dispatch_after://在一個時間段後向某個queue中添加一個block方法
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)3*NSEC_PER_SEC);//可以獲得一個距某個時間點相當時長的時間,第一個參數為開始時間,現在設定的為目前時間,第二個參數為時間流失的數值,現在是3s
dispatch_after(time, dispatch_get_main_queue(),
^{
NSLog(@"hello");
});//使用dispatch_after方法,在time後向主線程隊列添加一個block方法
注意:dispatch_after與performSelector:withObject:afterDelay:的差別,後者為相應時間後執行該方法;前者為相應時間後向隊列添加方法,而這個方法并不一定立刻執行
2、dispatch_group_t
dispatch_group_t:多線程組,将一些queue,添加到這個中,可以實作監測這些queue全部完成的狀态,如果為Serial就沒有使用這個的必要了
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//建立queue
dispatch_group_t group = dispatch_group_create();//建立group
dispatch_group_async(group, queue, ^{});//向group中添加queue及其block方法,第一個參數為組名,第二個參數為queue名,第三個參數為block方法
dispatch_group_async(group, queue, ^{});//向group中添加queue及其block方法
dispatch_group_async(group, queue, ^{});//向group中添加queue及其block方法
dispatch_group_async(group, queue, ^{});//向group中添加queue及其block方法
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//可以通過wait方法設定監測時間,現在設定的是永遠,也能用dispatch_time_t進行特定時間的設定
dispatch_release(group);//因為是create出來的,是以需要release
3、dispatch_barrier_async
dispatch_barrier_async(someQueue, ^{}):用于在某些一些動作中插入一些動作,一般配合create出來的concurrent類型queue使用,Serial就沒有使用這個的必要了
dispatch_queue_t queue = dispatch_queue_create("", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_barrier_async(queue, ^{});//會将queue對應的block方法加入queue,并等此方法結束後再繼續queue裡的剩下block方法
dispatch_async(queue, ^{});
dispatch_async(queue, ^{});
dispatch_release(queue);//因為是create出來的,是以需要release
4、 dispatch_sync
dispatch_sync(someQueue, ^{})與dispatch_barrier_sync(someQueue, ^{})同步運作,會死鎖,但是不要用在MainThread或者在非concurrent的本身queue裡面進行自己的sync
5、dispatch_apply
dispatch_apply(10, someQueue, ^{}):用于将某個block代碼塊按指定次數重複追加到queue中,并等待這些block全部執行完畢,是以推薦用在async中
NSArray *array = [NSArray arrayWithObjects:@"",@"",@"",@"",@"",@"",@"", nil];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue,
^{
dispatch_apply(array.count, queue, ^(size_t index)//會将數組的長度作為次數,将block代碼塊添加到queue中,并等待其中所有block執行完畢
{
NSLog(@"%@",[array objectAtIndex:index]);
});
});
6、dispatch_suspend&dispatch_resume
dispatch_suspend(someQueue)&dispatch_resume(someQueue):用于将挂起時queue中尚未執行的處理停止以及繼續開始
7、dispatch_semaphore_t
dispatch_semaphore_t:計數信号,為了更細分的保證不會造成程式的變量被同時通路
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//初始化semaphore的計數,并設最大為1
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
for(int i = 0;i<10000;i++)//在循環中如果不用semaphore,則async出來的線程們可能會同時通路array,造成異常
{
dispatch_async(queue,
^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//第一個參數為技術信号,第二個參數為等待時間,現在是一直等待直到semaphore的值等于1
[array addObject:[NSNumber numberWithInt:i]];//排他成功後,即semaphore等于1時,執行數組添加對象操作,同時将semaphore值變為0
dispatch_semaphore_signal(semaphore);//将semaphore的值增為1
});
}
dispatch_release(semaphore);//因為是create出來的,是以需要release
8、dispatch_once_t
dispatch_once_t:保證其block塊在應用中隻執行一次
+(MyClass *)sharedInstance
{
static MyClass *sharedManager;
static dispatch_once_t onceToken;//通過這個onceToken使得下面的執行個體化隻做一次
dispatch_once(&onceToken, ^{
sharedManager = [[MyClass alloc] init];
});
return sharedManager;
}
參考:人民郵電出版社,《Objective-C進階程式設計 ios與osx多線程和記憶體管理》