Grand Central Dispatch (GCD)是Apple開發的一個多核程式設計的解決方法
1.常用的方法dispatch_async 耗時的操作
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新介面
});
});
1.Dispatch Group的使用
(void)downloadImages {
並行執行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 下載第一張圖片 NSString *url1 = @"<http://car0.autoimg.cn/upload/spec/9579/u_20120110174805627264.jpg>"; UIImage *image1 = [self imageWithURLString:url1]; // 下載第二張圖片 NSString *url2 = @"<http://hiphotos.baidu.com/lvpics/pic/item/3a86813d1fa41768bba16746.jpg>"; UIImage *image2 = [self imageWithURLString:url2]; // 回到主執行緒顯示圖片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView1.image = image1; self.imageView2.image = image2; });
});
}
兩張圖片的下載過程並不需要按順序執行,併發執行它們可以提高執行速度
+(void)dispatch{
//得到佇列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// 耗時的操作
// 建立一個組
dispatch_group_t group = dispatch_group_create();
// 建立一組任務
dispatch_group_async(group, queue, ^{
NSLog(@"並行執行執行緒一");
});
// 建立二組任
dispatch_group_async(group, queue, ^{
NSLog(@"並行執行執行緒二");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 更新介面
NSLog(@"主執行緒更新介面");
});
});
}
/// 另一種寫法
(void)requestDatasGroup {
// 建立排程組
dispatch_group_t group = dispatch_group_create();
// 建立佇列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"介面 A 資料請求完成"); dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"介面 B 資料請求完成"); dispatch_group_leave(group);
});
NSLog(@”我是最開始執行的,非同步操作裡的列印是後執行的”);
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"介面 A 和介面 B 的資料請求都已經完畢!, 開始合併兩個介面的資料");
});
}
3、dispatch_barrier_async的使用
順序執行
dispatch_barrier_async是在前面的任務執行結束後它才執行,而且它後面的任務等它執行完成之後才會執行
例子程式碼如下
dispatch_queue_t queue = dispatch_queue_create(“gcdtest.rongfzh.yc”, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
列印結果:
2012-09-25 16:20:33.967 gcdTest[45547:11203] dispatch_async1
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_async2
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_barrier_async
2012-09-25 16:20:40.970 gcdTest[45547:11303] dispatch_async3
4、dispatch_apply
執行某個程式碼片段N次。
dispatch_apply(5, globalQ, ^(size_t index) {
// 執行5次
});
5,gcd 延時操作
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0/延遲執行時間/ * NSEC_PER_SEC));
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
[self reciveNotification:userInfo];
});
其他方法
#pragma mark 第一種解決縣城的問題的方法,nsobject提供的方法
-(void)NSObjectThread:(UIButton *)button{
[self performSelectorInBackground:@selector(click:) withObject:button];
//優點:寫法特別簡單.能快速開闢一個臨時執行緒
//缺點:不能保證執行緒使用時資料的絕對安全
}
#pragma mark 第二種方式
-(void)NSThreadAction:(UIButton *)button{
//NSThread 本身就是一個執行緒類,它可以控制執行緒休眠或者建立..
//當前的主執行緒
NSLog(@"%@",[NSThread currentThread]);
//主執行緒休眠3s
// [NSThread sleepForTimeInterval:3];
// NSLog(@”0002112121”);
//如果用建立物件,建立出來的就是新的執行緒..
NSThread *thread=[[[NSThread alloc] initWithTarget:self selector:@selector(click:) object:nil] autorelease];
//可以給新的執行緒物件起名
thread.name=@"kitty";
//啟動子執行緒.
[thread start];
//優點:可以直接通過建立的方式來控制執行緒.
//缺點:什麼都需要手動設定,包括名,開始.太麻煩..
}
#pragma mark 第三種 NSOperation 任務
-(void)operationQueue:(UIButton *)button{
//佇列和任務一起配合使用解決多執行緒的問題..
//佇列:佇列中通過一個執行緒池來管理所有閒置的執行緒,這樣就可以提高執行緒的重用率,避免重複的建立執行緒,,整合資源
//優點:內部不需要關心執行緒的安全問題,用起來相對簡單//
//缺點:效率稍微優點低...
NSOperationQueue *queue=[[NSOperationQueue alloc] init];
//設定最大併發數..
[queue setMaxConcurrentOperationCount:2];
MyOperation *op1=[[MyOperation alloc] init];
MyOperation *op2=[[MyOperation alloc] init];
MyOperation *op3=[[MyOperation alloc] init];
MyOperation *op4=[[MyOperation alloc] init];
MyOperation *op5=[[MyOperation alloc] init];
//把任務加到佇列裡
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4];
[queue addOperation:op5];
}
=============
MyOperation 繼承於 NSOperation
@implementation MyOperation
-(void)main{
// 要執行的操作。。
}
@end
//利用GCD的dispatch_once的方法實現單利模式
- (instancetype)defaultManager {
staticMusicPlayerViewController *_instance =nil;
staticdispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
_instance = [[selfalloc] init];
});
return_instance;
}
6.後臺執行
GCD的另一個用處是可以讓程式在後臺較長久的執行。在沒有使用GCD時,當app被按home鍵退出後,app僅有最多5秒鐘的時候做一些儲存或清理資源的工作。但是在使用GCD後,app最多有10分鐘的時間在後臺長久執行。這個時間可以用來做清理本地快取,傳送統計資料等工作。
// AppDelegate.h檔案
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask;
// AppDelegate.m檔案
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self beingBackgroundUpdateTask];
// 在這裡加上你需要長久執行的程式碼
[self endBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask
{
self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void)endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結