iOS多線程邂逅,ios多線程
1.線程之間的通訊
//有一個特別耗時的操作,比如說網路請求,開啟子線程去請求網路,我們一般是要在主線程更新UI,如何從子線程跳轉到主線程?
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (IBAction)downLoadImage:(id)sender {
[self performSelectorInBackground:@selector(loadImage) withObject:nil];
}
- (void)loadImage {
NSLog(@"loadImage - %@",[NSThread currentThread]);
NSString * urlString = @"http://design.yesky.com/uploadImages/2009/335/20091201140951681.jpg";
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage * image = [UIImage imageWithData:data];
//waitUntilDone
// [self performSelectorOnMainThread:@selector(changeMainThread:) withObject:image waitUntilDone:NO];
// [self performSelector:@selector(changeMainThread:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
// waitUntilDone:是什麼意思?
// YES:等待loadImage:這個方法執行完畢之後,再執行當前線程後續的操作
// NO:不等待loadImage:這個方法執行完畢,就執行當前線程後續的操作
NSLog(@"waitUntilDone");
// self.imageView.image = image;
}
2.GCD基礎
核心概念
任務:block裡需要執行的操作
隊列:把任務添加進入隊列中,按照先進先出的原則來執行任務
串列隊列:一個一個的執行
並行隊列:可以讓多個任務並發(同時)執行(自動開啟多個線程同時執行任務)並發功能只有在非同步(dispatch_async)函數下才有效。
同步任務:不會開闢新的線程,任務在當前的線程中執行,同時任務是立刻執行
非同步任務:會開闢新的線程(主隊列不可以),任務在新開闢的線程執行(主隊列在主線程中執行),不是立刻 執行任務
同步任務串列隊列:不會開啟新的線程,當前的線程中順序執行任務
同步任務並行隊列:不會開啟新的線程,當前的線程中執行任務,立刻執行任務
非同步任務串列隊列:會開闢一個新的線程,在新開闢的線程中執行任務,不是立刻執行
非同步任務並行隊列:會開闢新的線程,在新開闢的線程中執行任務,任務的完成順序是無序的,不是立刻執行
主隊列(特殊的串列隊列):任務只會在主線程中調度,不會開闢新的線程(一般用於重新整理UI)
非同步任務主隊列:不會開闢新的線程,當前的線程中執行任務,不會立刻執行任務
同步任務主隊列:死結
全域隊列(並行隊列):全域隊列供給應用程式共用,可以設定優先權
開闢新的線程:由任務決定,同步任務不會開闢新的線程,非同步任務會開闢新的線程(主隊列不會開闢新的線程)
開闢多少線程:由隊列決定,串列隊列只會開啟一個線程,並行隊列會開闢多個線程,具體多少個由任務的數量和GCD的底層來決定的
*/
- (void)gcdTest6 {
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"1");
//在主隊列裡執行同步操作,產生死結
//原因:同步線程等待主線程結束,才會執行任務。主線程等待同步立即執行,才會執行下一個任務。
dispatch_sync(queue, ^{
NSLog(@"2");
});
NSLog(@"3");
}
- (void)gcdTest5 {
// 主隊列就是一種特殊的串列隊列
// 特點:專門負責在主線程上調度任務,不會再子線程中去調度任務,無論是同步或非同步中調用任務都只會在主線程上面執行
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"開始");
for (NSInteger i = 0; i < 10; i ++) {
//主隊列執行非同步作業,非同步作業有一個等待的過程
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
NSLog(@"結束");
}
//並發隊列:多個線程同時執行
//同步操作:不會開啟新的線程
//執行結果:不會開啟新的線程,立即執行
- (void)gcdTest4 {
dispatch_queue_t queue = dispatch_queue_create("com.bjsxt", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"開始");
for (NSInteger i = 0 ; i < 10; i ++ ) {
dispatch_sync(queue, ^{
NSLog(@"%@,%@",[NSThread currentThread],@(i));
});
}
NSLog(@"結束");
}
//並發隊列:多個線程同時執行
//非同步作業:會開啟新的線程
//執行結果:會開闢新的線程,在新開闢的線程中執行任務,任務的完成順序是無序的,不是立刻執行
- (void)gcdTest3 {
//開啟並發隊列
dispatch_queue_t queue = dispatch_queue_create("com.bjsxt", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"開始");
for (NSInteger i = 0 ; i < 10; i ++ ) {
//執行非同步作業
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
NSLog(@"結束");
}
//串列隊列:一個一個執行
//非同步作業:會開啟新的線程
//執行結果:開啟一個新的線程,在新開闢的線程中執行任務,不是立刻執行
- (void)gcdTest2 {
dispatch_queue_t queue = dispatch_queue_create("com.bjsxt", NULL);
NSLog(@"開始");
for (NSInteger i = 0 ; i < 10; i ++ ) {
//非同步請求
dispatch_async(queue, ^{
NSLog(@"%@,%@",[NSThread currentThread],@(i));
});
}
NSLog(@"結束");
}
//串列隊列:一個一個執行
//同步操作:不開啟新的線程
//執行結果:不開啟新的線程,一個一個順序執行
- (void)gcdTest1 {
//label:隊列名
//attr:隊列屬性(串列,並發)
//DISPATCH_QUEUE_SERIAL 串列
//DISPATCH_QUEUE_CONCURRENT 並發
//#define DISPATCH_QUEUE_SERIAL NULL
dispatch_queue_t queue = dispatch_queue_create("com.bjsxt",DISPATCH_QUEUE_SERIAL);
NSLog(@"開始");
//同步操作
//操作任務:block
dispatch_sync(queue, ^{
//列印當前線程
NSLog(@"%@",[NSThread currentThread]);
});
NSLog(@"結束");
}
3.GCD線程之間通訊
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (IBAction)downLoadImage:(id)sender {
NSLog(@"%@",[NSThread currentThread]);
//擷取全域隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//執行非同步作業
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
NSString * urlString = @"http://design.yesky.com/uploadImages/2009/335/20091201140951681.jpg";
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage * image = [UIImage imageWithData:data];
//返回主線程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
self.imageView.image = image;
});
});
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//同步操作用途
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
NSLog(@"登入");
});
dispatch_async(queue, ^{
NSLog(@"下載鬥破蒼穹");
});
dispatch_async(queue, ^{
NSLog(@"下載大主宰");
});
}