GCD多线程
2017-10-24 本文已影响0人
赤焰军少帅林殊
目前, GCD 有三种队列类型.
- main queue: 主队列.
- global queue: 全局队列.
- custom queue: 自定义队列.
- 并行队列 + 同步执行
不会开启新线程,执行完一个任务,再执行下一个任务
NSLog(@"syncMain---begin");
dispatch_queue_t queue= dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);//主队列
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncConcurrent---end");
同时我们还可以看到,所有任务都在打印的syncConcurrent---begin和syncConcurrent---end之间,这说明任务是添加到队列中马上执行的。
2.2. 并行队列 + 异步执行
可同时开启多线程,任务交替执行
NSLog(@"syncMain---begin");
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncConcurrent---end");
另一方面可以看出,所有任务是在打印的syncConcurrent---begin和syncConcurrent---end之后才开始执行的。说明任务不是马上执行,而是将所有任务添加到队列之后才开始异步执行。
- 串行队列 + 同步执行
不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
NSLog(@"syncMain---begin");
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncSerial---end");
同时我们还可以看到,所有任务都在打印的syncConcurrent---begin和syncConcurrent---end之间,这说明任务是添加到队列中马上执行的。
- 串行队列 + 异步执行
会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务
NSLog(@"syncMain---begin");
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncSerial---end");
另一方面可以看出,所有任务是在打印的syncConcurrent---begin和syncConcurrent---end之后才开始执行的。说明任务不是马上执行,而是将所有任务添加到队列之后才开始同步执行。
- 主队列 + 同步执行
互等卡住不可行(在主线程中调用)死锁
NSLog(@"syncMain---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncMain---end");
这时候,我们惊奇的发现,在主线程中使用主队列 + 同步执行,任务不再执行了,而且syncMain---end也没有打印。这是为什么呢?
这是因为我们在主线程中执行这段代码。我们把任务放到了主队列中,也就是放到了主线程的队列中。而同步执行有个特点,就是对于任务是立马执行的。那么当我们把第一个任务放进主队列中,它就会立马执行。但是主线程现在正在处理syncMain方法,所以任务需要等syncMain执行完才能执行。而syncMain执行到第一个任务的时候,又要等第一个任务执行完才能往下执行第二个和第三个任务。
那么,现在的情况就是syncMain方法和第一个任务都在等对方执行完毕。这样大家互相等待,所以就卡住了,所以我们的任务执行不了,而且syncMain---end也没有打印。
多个主队列同步执行造成死锁
- 主队列 + 异步执行
只在主线程中执行任务,执行完一个任务,再执行下一个任务`
NSLog(@"asyncMain---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncMain---end");