標籤:
基礎知識:
下午9:09
一、基礎概念
1、什麼是GCD
全稱是Grand Central Dispath 純C語言編寫,提供非常多且強大的函數,是目前推薦的多線程開發方法,NSOperation便是基於GCD的封裝
2、GCD的優勢
1.為多核的並行運算提出瞭解決方案
2.GCD會自動利用更多的CPU核心,比如 雙核,四核
3、GCD自動管理線程的生命週期(建立線程,調度任務,銷毀線程)
4.程式員只需告訴GCD想要執行什麼任務,不需要編寫任何線程管理代碼
3、GCD中的兩個核心概念
1.任務:執行什麼操作
2.隊列:用來存放任務
4、隊列可分為兩大類型
(1)串列隊列(Serial Dispatch Queue): 只能有一個線程,加入到隊列中的操作按添加順序依次執行,一個任務執行完畢後 才能執行下一個任務
(2)並發隊列(Concurrent Dispatch Queue): 可以有多個線程,操作進來之後他會將這些線程安排在可用的處理器上,同時保證先進來的任務優先處理
(3)還有一個特殊的隊列就是主隊列,主隊列中永遠只有一個線程-主線程,用來執行主線程的操作任務
5、採用GCD做多線程,可抽象為兩步
1、找到隊列
2、在隊列中用同步或者非同步方式執行任務
6.執行隊列中任務的兩種方式
1、同步:只能在當前線程執行任務,不具備開啟新線程的能力
2、非同步:可以在新的線程中執行任務,具備開啟新線程的能力
7、GCD建立的線程任務有四種方式
二、串列同步 串列非同步 並行同步 並行非同步使用
#pragma mark-----串列同步 dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL); dispatch_sync(serialQueue, ^{// NSLog(@"%@",[NSThread currentThread]); });#pragma mark-----串列非同步 dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue1, ^{// NSLog(@"%@",[NSThread currentThread]); });#pragma mark----並行同步 dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(concurrentQueue, ^{// NSLog(@"%@",[NSThread currentThread]); });#pragma mark----並行非同步 dispatch_queue_t concurrentQueue1 = dispatch_queue_create("concurrentQueue1", DISPATCH_QUEUE_CONCURRENT); dispatch_async(concurrentQueue1, ^{ NSLog(@"%@",[NSThread currentThread]); });
三、具體執行個體 使用GCD載入多張圖片
#define kurl @"http://store.storeimages.cdn-apple.com/8748/as-images.apple.com/is/image/AppleInc/aos/published/images/s/38/s38ga/rdgd/s38ga-rdgd-sel-201601?wid=848&hei=848&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1454777389943"@interface MoreImageViewViewController (){ int imageTag; UIImageView *myImageView; dispatch_queue_t concurentQueue; NSOperationQueue *operationQueues;}@end- (void)viewDidLoad { [super viewDidLoad]; imageTag = 100; self.view.backgroundColor = [UIColor greenColor]; self.edgesForExtendedLayout = UIRectEdgeNone; [self controlBtn]; /* 1、建立多個視圖 2、找到並行隊列 3、給這個並行隊列指定多個任務 4、在子線程載入網路資源 5、回到主線程 6、更新UI */// 1、建立多個視圖 for (int i=0; i<3; i++) { for (int j=0; j<2; j++) { myImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10+j*200, 40+i*200, 190, 190)]; myImageView.backgroundColor = [UIColor orangeColor]; myImageView.tag = imageTag++; [self.view addSubview:myImageView]; } }// 2、找到並行隊列// 使用下面這個方式不按順序 因為下面這句找的是 系統的全域並行隊列// concurentQueue = dispatch_get_global_queue(0, 0);// 這個方式是按順序的 用的串列隊列 concurentQueue = dispatch_queue_create("concurentQueue", DISPATCH_QUEUE_SERIAL); // 3、指定任務 for (int index=0; index<6; index++) { dispatch_async(concurentQueue, ^{ [NSThread sleepForTimeInterval:1];// 載入網路資源 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]]; UIImage *image = [UIImage imageWithData:data]; // 5、回到主線程 dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_sync(mainQueue, ^{ // 6、重新整理UI for (int i=0; i<6; i++) { UIImageView *iamgeView = [self.view viewWithTag:100+index]; iamgeView.image = image; } }); }); } }以下兩個方法是暫停和開啟線程的- (void)controlBtn{ UISegmentedControl *segment = [[UISegmentedControl alloc]initWithItems:@[@"暫停",@"開啟",]]; segment.frame = CGRectMake(50, 620, 300, 50); segment.apportionsSegmentWidthsByContent = YES; [self.view addSubview:segment]; [segment addTarget:self action:@selector(clickSegment:) forControlEvents:UIControlEventValueChanged];}- (void)clickSegment:(UISegmentedControl *)sender { switch (sender.selectedSegmentIndex) { case 0:{ // 暫停隊列 dispatch_suspend(concurentQueue); }break; case 1:{ // 恢複隊列 dispatch_resume(concurentQueue); }break; } }
iOS 開發線程 gcd