对于线程与队列的关系, 每次想起都不甚明了, 找个地方备注一下.
1、GCD简介
GCD(Grand Central Dispatch),是苹果提供的一个解决多线程开发的解决方案。GCD会自动管理线程的生命周期(创建线程,调度任务,销毁线程),完全不需要我们管理,我们只需要告诉干什么就行.
2、创建任务队列
GCD中的队列主要分两种。
- 并发队列:允许多个任务同时执行。
- 串行队列:任务按顺序依次执行。
- 系统默认有一个和主线程绑定的串行队列,还有一个全局的并发队列。这两个队列都可以通过响应的方法来获得。
2.1、获得主线程的串行队列
调用这个方法获取主线程队列时,该队列是由主线程来自动创建的。
dispatch_queue_t mainQueue = dispatch_get_main_queue();
2.2、获得全局的并发队列
获取全局并发队列的方法中有两个参数,第二个参数暂时没有使用,默认传值0就好。第一个参数表示队列的优先级,其中优先级主要分为4种。
- DISPATCH_QUEUE_PRIORITY_HIGH 2,优先级高
- DISPATCH_QUEUE_PRIORITY_DEFAULT 0,默认优先级,中
- DISPATCH_QUEUE_PRIORITY_LOW -2,优先级低
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN,后台模式,优先级最低
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.3、创建自定义的队列
创建自定义的队列主要有两种,一种是串行队列,一种是并行队列。在创建自定义队列时会需要传两个参数,第一个为队列的名称,第二个为表示队列类型的常量(串行还是并行)。
DISPATCH_QUEUE_SERIAL //串行队列
//串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.lysongzi.serial", DISPATCH_QUEUE_SERIAL);
DISPATCH_QUEUE_CONCURRENT //并行队列
//并行队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.lysongzi.concurrent", DISPATCH_QUEUE_CONCURRENT);
3、同步&异步
创建好队列, 然后把任务添加到队列中, 这里牵涉到同步或者异步两种方式
串行队列
- 同步, 其会在当前线程立即执行添加的任务
- 异步, 其会新创建一个新的线程来执行任务(只有一个)
-(void)testSerialQueue
{
//创建串行队列,传入参数为DISPATCH_QUEUE_SERIAL
self.serialQueue = dispatch_queue_create("com.lysongzi.serial", DISPATCH_QUEUE_SERIAL);
//同步执行队列中的任务,会立即在当前线程执行该任务
dispatch_sync(self.serialQueue, ^{
NSLog(@"这里是同步执行的串行队列01。===> %@", [NSThread currentThread]);
});
//异步执行任务,会新开一个线程,多个任务按顺序执行
dispatch_async(self.serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"串行01 ===> %d ===> %@", i, [NSThread currentThread]);
}
});
dispatch_sync(self.serialQueue, ^{
NSLog(@"这里是同步执行的串行队列02。===> %@", [NSThread currentThread]);
});
dispatch_async(self.serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"串行02 ===> %d ===> %@", i, [NSThread currentThread]);
}
});
dispatch_async(self.serialQueue, ^{
for (int i = 0; i < 3; i++) {
NSLog(@"串行03 ===> %d ===> %@", i, [NSThread currentThread]);
}
});
}
看一下输出结果。我们会发现使用同步方式执行的任务都会被立即执行,并且是在当前线程(主线程)中执行的。而用异步方式的任务则会在新创建的线程(number=2)中执行,并且它们是按照一定顺序执行的(串行01->串行02->串行03)。
2016-03-20 20:17:34.123 Demo[4084:422492] 这里是同步执行的串行队列01。===> <NSThread: 0x100103080>{number = 1, name = main}
2016-03-20 20:17:34.125 Demo[4084:422514] 串行01 ===> 0 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.125 Demo[4084:422514] 串行01 ===> 1 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.125 Demo[4084:422514] 串行01 ===> 2 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.126 Demo[4084:422492] 这里是同步执行的串行队列02。===> <NSThread: 0x100103080>{number = 1, name = main}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行02 ===> 0 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行02 ===> 1 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行02 ===> 2 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行03 ===> 0 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行03 ===> 1 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
2016-03-20 20:17:34.746 Demo[4084:422514] 串行03 ===> 2 ===> <NSThread: 0x100103a70>{number = 2, name = (null)}
并发队列
- 同步, 任务在当前线程立即执行
异步, 任务都会放到新创建的线程, 如果线程中任务没有执行完成, 新任务会另开新的线程, 不按顺序执行, 有执行完的会放到已执行完线程执行, 合理利用线程.
-(void)testConcurrentQueue { //创建并发队列,传入参数为DISPATCH_QUEUE_CONCURRENT self.concurrentQueue = dispatch_queue_create("com.lysongzi.concurrent", DISPATCH_QUEUE_CONCURRENT); //同步执行队列中的任务,会立即执行该任务 dispatch_sync(self.concurrentQueue, ^{ for (int i = 0; i < 3; i++) { NSLog(@"并发同步01 ===> %d ===> %@", i, [NSThread currentThread]); } }); dispatch_sync(self.concurrentQueue, ^{ for (int i = 0; i < 3; i++) { NSLog(@"并发同步02 ===> %d ===> %@", i, [NSThread currentThread]); } }); //异步执行并发队列 dispatch_async(self.concurrentQueue, ^{ for (int i = 0; i < 5; i++) { NSLog(@"并发异步01 ===> %d ===> %@", i, [NSThread currentThread]); } }); dispatch_async(self.concurrentQueue, ^{ for (int i = 0; i < 5; i++) { NSLog(@"并发异步02 ===> %d ===> %@", i, [NSThread currentThread]); } }); dispatch_async(self.concurrentQueue, ^{ for (int i = 0; i < 5; i++) { NSLog(@"并发异步03 ===> %d ===> %@", i, [NSThread currentThread]); } }); }
结果如下所示, 开辟了3个线程, 当线程2的任务执行完成之后,会执行接下来并发执行的任务
2016-02-20 20:52:18.376 Demo[4223:436777] 并发同步01 ===> 0 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.377 Demo[4223:436777] 并发同步01 ===> 1 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.377 Demo[4223:436777] 并发同步01 ===> 2 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.377 Demo[4223:436777] 并发同步02 ===> 0 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.377 Demo[4223:436777] 并发同步02 ===> 1 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.377 Demo[4223:436777] 并发同步02 ===> 2 ===> <NSThread: 0x100108c80>{number = 1, name = main}
2016-02-20 20:52:18.378 Demo[4223:436826] 并发异步03 ===> 0 ===> <NSThread: 0x100700110>{number = 3, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436826] 并发异步03 ===> 1 ===> <NSThread: 0x100700110>{number = 3, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436825] 并发异步02 ===> 0 ===> <NSThread: 0x1002000a0>{number = 2, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436826] 并发异步03 ===> 2 ===> <NSThread: 0x100700110>{number = 3, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436825] 并发异步02 ===> 1 ===> <NSThread: 0x1002000a0>{number = 2, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436826] 并发异步03 ===> 3 ===> <NSThread: 0x100700110>{number = 3, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436825] 并发异步02 ===> 2 ===> <NSThread: 0x1002000a0>{number = 2, name = (null)}
2016-02-20 20:52:18.378 Demo[4223:436826] 并发异步03 ===> 4 ===> <NSThread: 0x100700110>{number = 3, name = (null)}
2016-02-20 20:52:18.379 Demo[4223:436824] 并发异步01 ===> 0 ===> <NSThread: 0x10010aec0>{number = 4, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436825] 并发异步02 ===> 3 ===> <NSThread: 0x1002000a0>{number = 2, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436824] 并发异步01 ===> 1 ===> <NSThread: 0x10010aec0>{number = 4, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436825] 并发异步02 ===> 4 ===> <NSThread: 0x1002000a0>{number = 2, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436824] 并发异步01 ===> 2 ===> <NSThread: 0x10010aec0>{number = 4, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436824] 并发异步01 ===> 3 ===> <NSThread: 0x10010aec0>{number = 4, name = (null)}
2016-02-20 20:52:18.384 Demo[4223:436824] 并发异步01 ===> 4 ===> <NSThread: 0x10010aec0>{number = 4, name = (null)}
tips: 1.主线程中同步执行会卡死
dispatch_sync(dispatch_get_main_queue(), ^{});
参考资料