多线程用于后台计算于界面刷新的分离,或将不同的计算任务分配到不同的线程一起开始执行,提高计算效率。
主要介绍一下iOS的GCD:
1. 基本概念:
串行队列:只有一个线程,加入到队列中的操作按添加顺序依次执行。并且还要保证在执行某个任务时,在它前面进入队列的所有任务肯定执行完了。对于每一个不同的串行队列,系统会为这个队列建立唯一的线程来执行代码。
并发队列:这个队列中的任务也是按照先来后到的顺序开始执行,注意是开始,但是它们的执行结束时间是不确定的,取决于每个任务的耗时。对于n个并发队列,GCD不会创建对应的n个线程而是进行适当的优化
同步执行:会阻塞当前线程 sync默认会在当前线程执行(系统优化)
异步执行:异步添加任务
同步执行 | 异步执行 | |
---|---|---|
串行队列 | 当前线程,一个一个执行 | 其他线程,一个一个执行 |
并行队列 | 当前线程,一个一个执行 | 开很多线程,一起执行 |
创建队列:
//SWIFT
let
queue = dispatch_queue_create(
"testQueue", nil);
let
queue = dispatch_queue_create(
"seriesQueue", DISPATCH_QUEUE_SERIAL)
//串行队列
let
queue = dispatch_queue_create(
"cocurrentQueue", DISPATCH_QUEUE_CONCURRENT)//并行队列
创建任务:
异步执行:
dispatch_async(<#queue#>, { () -> Void in
//code here
println(NSThread.currentThread())
})
同步执行:
dispatch_sync(<#queue#>, { () -> Void in
//code here
println(NSThread.currentThread())
})
典型错误分析:
界面都是在主线程中,主线程是串行线程。
viewDidAppear方法的代码相当于mainQueue的一个任务(假设任务A), 现在它里面加了个sync的{假设任务B}, 意味着任务B只有等任务A完成才能开始, 但是要完成任务A的话就必须先完成任务B,这样相互等待出现线程阻塞。
因此不能在主线程某个任务中创建其他同步任务。
2. 线程通信:
1 .一个线程传递数据给另一个线程
2 .在一个线程中执行完特定任务后,转到另一个线程继续执行任务
1. GCD 一个线程传递数据搭配另外一个xian'chen
1. `GCD`一个线程传递数据给另一个线程,如:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"donwload---%@", [NSThread currentThread]);
// 1.子线程下载图片
NSURL *url = [NSURL URLWithString:@"http://d.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 2.回到主线程设置图片
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"setting---%@ %@", [NSThread currentThread], image);
[self.button setImage:image forState:UIControlStateNormal];
});
});
}
- (
void)performSelectorOnMainThread:(SEL)aSelector withObject:(
nullable
id)arg waitUntilDone:(
BOOL)wait;- (
void)performSelector:(SEL)aSelector onThread:(
NSThread *)thr withObject:(
nullable
id)arg waitUntilDone:(
BOOL)wait
NS_AVAILABLE(
10_5,
2_0);
用法如下:
//点击屏幕开始执行下载方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self performSelectorInBackground:@selector(download) withObject:nil];
}
//下载图片
- (void)download
{
// 1.图片地址
NSString *urlStr = @"http://d.jpg";
NSURL *url = [NSURL URLWithString:urlStr];
// 2.根据地址下载图片的二进制数据
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(@"---end");
// 3.设置图片
UIImage *image = [UIImage imageWithData:data];
// 4.回到主线程,刷新UI界面(为了线程安全)
[self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];
// [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
}
- (void)downloadFinished:(UIImage *)image
{
self.imageView.image = image;
NSLog(@"downloadFinished---%@", [NSThread currentThread]);
}
【1】https://www.jianshu.com/p/fc69da0dce7a
【2】https://www.jianshu.com/p/0b0d9b1f1f19
【3】https://www.jianshu.com/p/51d67a0f3b87