一.队列 同步异步
关于这个我在前面的文章也写过,这里写个例子复习一下
代码语言:javascript复制1).串行队列同步执行:任务都在当前线程执行(同步),并且顺序执行(串行)
2).串行队列异步执行:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)
3).并发队列同步执行:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)
4).并发队列异步执行:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)
代码语言:javascript复制-(void)testCon_queue{
dispatch_queue_t con_queue = dispatch_queue_create("con", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(con_queue, ^{
dispatch_async(con_queue, ^{
NSLog(@"1----%@",NSThread.currentThread);
});
dispatch_sync(con_queue, ^{
NSLog(@"2----%@",NSThread.currentThread);
});
dispatch_sync(con_queue, ^{
NSLog(@"3----%@",NSThread.currentThread);
});
dispatch_async(con_queue, ^{
NSLog(@"4----%@",NSThread.currentThread);
});
dispatch_async(con_queue, ^{
NSLog(@"5----%@",NSThread.currentThread);
});
dispatch_async(con_queue, ^{
NSLog(@"6----%@",NSThread.currentThread);
});
});
}
代码语言:javascript复制1----<NSThread: 0x600001f8d580>{number = 4, name = (null)}
2----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
3----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
4----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
5----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
6----<NSThread: 0x600001f8d580>{number = 4, name = (null)}
代码语言:javascript复制2----<NSThread: 0x6000011af380>{number = 3, name = (null)}
1----<NSThread: 0x6000011aa780>{number = 4, name = (null)}
3----<NSThread: 0x6000011af380>{number = 3, name = (null)}
5----<NSThread: 0x6000011aa780>{number = 4, name = (null)}
6----<NSThread: 0x6000011aa1c0>{number = 5, name = (null)}
4----<NSThread: 0x6000011af380>{number = 3, name = (null)}
解释一下,1 4 5 6是并发队列异步执行,所以他们会在开辟的新线程中并行执行,谁先谁后不一定。符合
代码语言:javascript复制4).并发队列异步执行:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)
2 3是并发队列同步执行,他们在同一条线程上顺序执行,如结果所示,线程number=3,2了才3。符合
代码语言:javascript复制3).并发队列同步执行:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)
我们在上两个结果中也能看见,有异步任务的执行线程跟同步任务执行的线程相同,也有两个异步任务的执行线程相同,这是因为一旦线程任务完成,其他任务可能会复用这条线程,有线程池维护它们,没有必要创建过多的线程造成资源浪费
二.队列 同步异步 信号量
1.并发队列同步
代码语言:javascript复制-(void)testSem{
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
NSLog(@"1---%@",NSThread.currentThread);
dispatch_sync(queue, ^{
[self netWork_task_requestTime:2 completionHandle:^{
NSLog(@"2---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3---%@",NSThread.currentThread);
});
dispatch_sync(queue, ^{
[self netWork_task_requestTime:1 completionHandle:^{
NSLog(@"4---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"5---%@",NSThread.currentThread);
});
NSLog(@"6---%@",NSThread.currentThread);
});
}
- (void)netWork_task_requestTime:(int)time completionHandle:(void(^)(void))success {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
success();
});
}
image.png
解释:信号量初始为0,1输出,执行2后wait,把3和以后的阻塞,2秒后主线程返回,任务完成signal,信号量 1,继续往下执行。 第二个同步任务与第一个执行情况一样:执行4后wait,5和以后的阻塞,1秒后主线程返回,任务完成signal,信号量 1,继续往下执行。 因为是同步执行,所以6最后输出
2.并发队列异步 我们把代码改成如下:
代码语言:javascript复制-(void)testSem{
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
NSLog(@"1---%@",NSThread.currentThread);
dispatch_async(queue, ^{
[self netWork_task_requestTime:2 completionHandle:^{
NSLog(@"2---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3---%@",NSThread.currentThread);
});
dispatch_async(queue, ^{
[self netWork_task_requestTime:1 completionHandle:^{
NSLog(@"4---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"5---%@",NSThread.currentThread);
});
NSLog(@"6---%@",NSThread.currentThread);
});
}
image.png
image.png
解释:1 6大家都理解,咱们重点研究4 3 2 5和4 5 2 3 1 6输出后,进入并发异步逻辑,2 4执行,然后3 5被阻塞,4先返回是因为任务4只需1s完成,这时候signal,信号量加一,3和5其中一个可以得到执行,因为是同一并发队列(优先级一样)异步,谁先执行无须在意,但只能执行其中的一个,因为只放出一条可执行线程,然后再过1秒,2完成signal,3 5剩下的一个任务得以执行。
3.并发队列异步 同步
代码语言:javascript复制-(void)testSem{
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
NSLog(@"1---%@",NSThread.currentThread);
dispatch_async(queue, ^{
[self netWork_task_requestTime:2 completionHandle:^{
NSLog(@"2---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3---%@",NSThread.currentThread);
});
dispatch_sync(queue, ^{
[self netWork_task_requestTime:1 completionHandle:^{
NSLog(@"4---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"5---%@",NSThread.currentThread);
});
NSLog(@"6---%@",NSThread.currentThread);
});
}
image.png
相信经过上面的讲解,这里大家也很容易明白: 1输出后,2 4得以执行,但3被2阻塞,5 6被4阻塞,然后1秒后,4完成,5得以执行,因为是同步6再得以执行,再过1秒,2完成,3得以执行。
4.并发队列同步 异步
代码语言:javascript复制-(void)testSem{
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(queue, ^{
NSLog(@"1---%@",NSThread.currentThread);
dispatch_sync(queue, ^{
[self netWork_task_requestTime:2 completionHandle:^{
NSLog(@"2---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3---%@",NSThread.currentThread);
});
dispatch_async(queue, ^{
[self netWork_task_requestTime:1 completionHandle:^{
NSLog(@"4---%@",NSThread.currentThread);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"5---%@",NSThread.currentThread);
});
NSLog(@"6---%@",NSThread.currentThread);
});
}
image.png
我想这个结果你已经预料到了: 1执行之后,同步,所以等2秒后2完成,3得以执行,然后是异步,6执行,1秒后4完成,5执行。
总结:只要理解串行并发队列,同步异步,信号量机制,他们的关联使用也是小菜一碟,大家哪点不够明白就攻哪点,各个击破。