一、主隊列介紹
主隊列:是和主線程相關聯的隊列,主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列中得任務,都會放到主線程中執行。如果把任務放到主隊列中進行處理,那么不論處理函數是異步的還是同步的都不會開啟新的線程。
獲取主隊列的方式:
dispatch_queue_t queue=dispatch_get_main_queue();
1)使用異步函數執行主隊列中得任務,代碼示例:
//1.獲取主隊列
dispatch_queue_t queue=dispatch_get_main_queue();
//2.把任務添加到主隊列中執行
dispatch_async(queue, ^{
NSLog(@"下載圖片1----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片2----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下載圖片3----%@",[NSThread currentThread]);
});
//打印主線程
NSLog(@"主線程----%@",[NSThread mainThread]);
異步函數主隊列打印結果.png
總結:不會開啟新的線程
2)使用同步函數,在主線程中執行主隊列中得任務,會發生死循環,任務無法往下執行。示意圖如下:
死循環示意圖.png
二、簡單使用
1.在全局并發隊列中,分別用異步函數和同步函數執行任務1和任務2,問:任務1和任務2是在主線程執行還是子線程執行,還是單獨再開啟一個新的線程?
- (void)viewDidLoad {
[super viewDidLoad];
//NSThread隱式創建線程(自動啟動)
[self performSelectorInBackground:@selector(text) withObject:nil];
}
-(void)text{
NSLog(@"當前線程---%@",[NSThread currentThread]);
//創建全局的并發隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//異步函數
dispatch_async(queue, ^{
NSLog(@"NSLog(任務1所在的線程----%@",[NSThread currentThread]);
});
//同步函數
dispatch_sync(queue, ^{
NSLog(@"NSLog(任務2所在的線程----%@",[NSThread currentThread]);
});
}
答:任務1和任務2在不同子線程,任務1新開線程,任務2在當前線程,但都不在主線程。
任務1和任務2打印結果.png
2.開啟子線程,加載圖片
//當手指觸摸屏幕的時候,從網絡上下載一張圖片到控制器的view上顯示
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//1.獲取一個全局串行隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//2.把任務添加到隊列中執行
dispatch_async(queue, ^{
//3.從網絡上下載圖片
NSURL *url = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//4.回到主線程,展示圖片
dispatch_async(dispatch_get_main_queue(), ^{
[self.button setBackgroundImage:image forState:UIControlStateNormal];
});
});
}
運行效果.png
三、線程間的通信
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執行耗時的異步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主線程,執行UI刷新操作
});
});