一、主隊列介紹
主隊列:是和主線程相關(guān)聯(lián)的隊列,主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列中得任務(wù),都會放到主線程中執(zhí)行。
提示:如果把任務(wù)放到主隊列中進(jìn)行處理,那么不論處理函數(shù)是異步的還是同步的都不會開啟新的線程。
獲取主隊列的方式:
dispatch_queue_t?queue=dispatch_get_main_queue();
(1)使用異步函數(shù)執(zhí)行主隊列中得任務(wù),代碼示例:
//
//? YYViewController.m
//? 12-GCD的基本使用(主隊列)
//
//? Created by 孔醫(yī)己 on 14-6-25.
//? Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//打印主線程
NSLog(@"打印主線程--%@", [NSThread mainThread]);
//1.獲取主隊列
dispatch_queue_t queue=dispatch_get_main_queue();
//2.把任務(wù)添加到主隊列中執(zhí)行
dispatch_async(queue, ^{
NSLog(@"使用異步函數(shù)執(zhí)行主隊列中的任務(wù)1--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"使用異步函數(shù)執(zhí)行主隊列中的任務(wù)2--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"使用異步函數(shù)執(zhí)行主隊列中的任務(wù)3--%@",[NSThread currentThread]);
});
}
@end
執(zhí)行效果:

(2)使用同步函數(shù),在主線程中執(zhí)行主隊列中得任務(wù),會發(fā)生死循環(huán),任務(wù)無法往下執(zhí)行。示意圖如下:

二、基本使用
1.問題
任務(wù)1和任務(wù)2是在主線程執(zhí)行還是子線程執(zhí)行,還是單獨再開啟一個新的線程?
//
//? YYViewController.m
//? 13-GCD基本使用(問題)
//
//? Created by 孔醫(yī)己 on 14-6-25.
//? Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//開啟一個后臺線程,調(diào)用執(zhí)行test方法
[self performSelectorInBackground:@selector(test) withObject:nil];
}
-(void)test
{
NSLog(@"當(dāng)前線程---%@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//異步函數(shù)
dispatch_async(queue, ^{
NSLog(@"任務(wù)1所在的線程----%@",[NSThread currentThread]);
});
//同步函數(shù)
dispatch_sync(queue, ^{
NSLog(@"任務(wù)2所在的線程----%@",[NSThread currentThread]);
});
}
@end
打印結(jié)果:

2.開啟子線程,加載圖片
//
//? YYViewController.m
//? 14-GCD基本使用(下載圖片)
//
//? Created by 孔醫(yī)己 on 14-6-25.
//? Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
//當(dāng)手指觸摸屏幕的時候,從網(wǎng)絡(luò)上下載一張圖片到控制器的view上顯示
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.獲取一個全局串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//2.把任務(wù)添加到隊列中執(zhí)行
dispatch_async(queue, ^{
//打印當(dāng)前線程
NSLog(@"%@",[NSThread currentThread]);
//3.從網(wǎng)絡(luò)上下載圖片
NSURL *urlstr=[NSURL URLWithString:@"http://h.hiphotos.baidu.com/baike/w%3D268/sign=30b3fb747b310a55c424d9f28f444387/1e30e924b899a9018b8d3ab11f950a7b0308f5f9.jpg"];
NSData *data=[NSData dataWithContentsOfURL:urlstr];
UIImage *image=[UIImage imageWithData:data];
//提示
NSLog(@"圖片加載完畢");
//4.回到主線程,展示圖片
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
});
}
@end
顯示效果:

打印結(jié)果:

要求使用GCD的方式,在子線程加載圖片完畢后,主線程拿到加載的image刷新UI界面。
//
//? YYViewController.m
//? 14-GCD基本使用(下載圖片)
//
//? Created by 孔醫(yī)己 on 14-6-25.
//? Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
//當(dāng)手指觸摸屏幕的時候,從網(wǎng)絡(luò)上下載一張圖片到控制器的view上顯示
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.獲取一個全局串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//2.把任務(wù)添加到隊列中執(zhí)行
dispatch_async(queue, ^{
//打印當(dāng)前線程
NSLog(@"%@",[NSThread currentThread]);
//3.從網(wǎng)絡(luò)上下載圖片
NSURL *urlstr=[NSURL URLWithString:@"http://h.hiphotos.baidu.com/baike/w%3D268/sign=30b3fb747b310a55c424d9f28f444387/1e30e924b899a9018b8d3ab11f950a7b0308f5f9.jpg"];
NSData *data=[NSData dataWithContentsOfURL:urlstr];
UIImage *image=[UIImage imageWithData:data];
//提示
NSLog(@"圖片加載完畢");
//4.回到主線程,展示圖片
//? ? ? ? [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image=image;
//打印當(dāng)前線程
NSLog(@"%@",[NSThread currentThread]);
});
});
}
@end
打印結(jié)果:

好處:子線程中得所有數(shù)據(jù)都可以直接拿到主線程中使用,更加的方便和直觀。
三、線程間通信
從子線程回到主線程
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執(zhí)?耗時的異步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主線程,執(zhí)?UI刷新操作
});
});