一、同步执行 + 主队列
/**
* 同步执行 + 主队列
* 特点(主线程调用):互等卡主不执行。
* 特点(其他线程调用):不会开启新线程,执行完一个任务,再执行下一个任务。
*/
- (void)syncMain {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开启");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"结束");
}
运行结果:
currentThread---{number = 1, name = main}
开启
线程死锁。为什么呢?
- (void)syncMain {} ----> 任务A
,GCD同步任务 ----> 任务B
任务A在主队列,并且已经开始执行(打印出currentThread
),这个时候任务B被加入到主队列中,并且同步执行,且不能开新的线程。
任务B得等Block函数执行完成,才能返回,然而主队列是串行的,得等任务A执行完才能去执行任务B的Block。
造成了任务A在等任务B完成才能继续执行,但是串行队列中,又不能让任务B在任务A未完成之前开始执行,相互等待,造成了死锁。
二、同步执行 + 并发队列
/**
* 同步执行 + 并发队列
* 特点:在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。
*/
- (void)syncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开启");
dispatch_queue_t queue = dispatch_queue_create("syncConcurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"结束");
}
运行结果:
currentThread---{number = 1, name = main}
开启
1---{number = 1, name = main}
2---{number = 1, name = main}
结束
三、异步执行 + 并发队列
/**
* 异步执行 + 并发队列
* 特点:可以开启多个线程,任务交替(同时)执行。
*/
- (void)asyncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开启");
dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"结束");
}
运行结果:
currentThread---{number = 1, name = main}
开启
结束
1---{number = 5, name = (null)}
2---{number = 6, name = (null)}
四、同步执行 + 串行队列
/**
* 同步执行 + 串行队列
* 特点:不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。
*/
- (void)syncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开启");
dispatch_queue_t queue = dispatch_queue_create("syncSerial", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"结束");
}
运行结果:
currentThread---{number = 1, name = main}
开启
1---{number = 1, name = main}
2---{number = 1, name = main}
结束
五、异步执行 + 串行队列
/**
* 异步执行 + 串行队列
* 特点:会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务。
*/
- (void)asyncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"开启");
dispatch_queue_t queue = dispatch_queue_create("asyncConcurrent", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"结束");
}
运行结果:
currentThread---{number = 1, name = main}
开启
结束
1---{number = 4, name = (null)}
2---{number = 4, name = (null)}
六、其他函数用法
1、dispatch_after
- (void)GCDDelay {
NSLog(@"current_%@",[NSThread currentThread]);
//主队列延时
dispatch_time_t when_main = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_main, dispatch_get_main_queue(), ^{
NSLog(@"main_%@",[NSThread currentThread]);
});
//全局队列延时
dispatch_time_t when_global = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_global, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"global_%@",[NSThread currentThread]);
});
//自定义队列延时
dispatch_queue_t customeQue = dispatch_queue_create("customeQue", DISPATCH_QUEUE_SERIAL);
dispatch_time_t when_global_custom = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(when_global_custom, customeQue, ^{
NSLog(@"when_global_custom_%@",[NSThread currentThread]);
});
}
current_{number = 1, name = main}
main_{number = 1, name = main}
when_global_custom_{number = 7, name = (null)}
global_{number = 5, name = (null)}
我们可以看到,当队列是主队列
时,任务是在主线程
执行;当队列为全局或自定义时,任务是在子线程中执行
2、dispatch_once
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"current_%@",[NSThread currentThread]);
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
current_{number = 1, name = main}
{number = 1, name = main}
程序运行期间,只会执行一次打印,任务在主线程中执行
3、dispatch_group_async & dispatch_group_notify
- (void)GCDGroup {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"3---%@",[NSThread currentThread]);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
end_{number = 1, name = main}
1---{number = 6, name = (null)}
2---{number = 3, name = (null)}
3---{number = 3, name = (null)}
dispatch_group_async
在dispatch_get_global_queue
时会开辟新的线程执行任务,任务会在子线程中执行
dispatch_group_notify
只会在dispatch_group_async
都执行完后才会执行
4、dispatch_barrier_async
- (void)GCDBarrier {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
NSLog(@"1---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"2---%@",[NSThread currentThread]);
});
//同步sync
dispatch_barrier_sync(myQueue, ^{
NSLog(@"barrier---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"3---%@",[NSThread currentThread]);
});
dispatch_async(myQueue, ^{
NSLog(@"4---%@",[NSThread currentThread]);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
myQueue为自定义时:
start_{number = 1, name = main}
2---{number = 6, name = (null)}
1---{number = 5, name = (null)}
barrier---{number = 1, name = main}
end_{number = 1, name = main}
3---{number = 5, name = (null)}
4---{number = 6, name = (null)}
myQueue为:dispatch_get_global_queue(0,0)时
start_{number = 1, name = main}
barrier---{number = 1, name = main}
1---{number = 6, name = (null)}
2---{number = 7, name = (null)}
3---{number = 6, name = (null)}
end_{number = 1, name = main}
4---{number = 4, name = (null)}
- 当队列为
自定义
时,使用dispatch_barrier_sync ()
后,任务3、4
必须等任务1、2
执行完后才能执行 - 当队列是
dispatch_get_global_queue(0,0)
时,就算使用了dispatch_barrier_sync ()
,执行顺序随机不固定 - 当队列是
dispatch_get_main_queue()
时,死锁
5、dispatch_apply
- (void)GCDApply {
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//重复执行
dispatch_apply(5, myQueue, ^(size_t i) {
NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
});
}
myQueue为串行:
start_{number = 1, name = main}
第0次_{number = 1, name = main}
第1次_{number = 1, name = main}
第2次_{number = 1, name = main}
第3次_{number = 1, name = main}
第4次_{number = 1, name = main}
end_{number = 1, name = main}
myQueue为并行:
start_{number = 1, name = main}
第3次_{number = 6, name = (null)}
第2次_{number = 4, name = (null)}
第0次_{number = 1, name = main}
第1次_{number = 7, name = (null)}
第4次_{number = 5, name = (null)}
end_{number = 1, name = main}
- 用于重复执行某个任务
- 任务队列是
串行队列
时,重复执行的任务会按顺序
执行 - 任务队列是
并行队列
时,重复执行的任务会并发
执行
6、dispatch_semaphore_create & dispatch_semaphore_wait & dispatch_semaphore_signal
- (void)GCDSemaphor {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//创建信号量,初始值不能小于0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//重复执行
dispatch_apply(5, myQueue, ^(size_t i) {
//等待降低信号量,也就是信号量-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"第%@次_%@",@(i),[NSThread currentThread]);
//提高信号量,也就是信号量+1
dispatch_semaphore_signal(semaphore);
});
NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
第0次_{number = 1, name = main}
第1次_{number = 1, name = main}
第2次_{number = 1, name = main}
第3次_{number = 1, name = main}
第4次_{number = 1, name = main}
end_{number = 1, name = main}
异步任务使用
- (void)GCDSemaphorAsync {
NSLog(@"start_%@",[NSThread currentThread]);
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
//创建信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(myQueue, ^{
NSLog(@"第一次任务开始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第一次任务结束_%@",[NSThread currentThread]);
//会将信号量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(myQueue, ^{
NSLog(@"第二次任务开始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第二次任务结束_%@",[NSThread currentThread]);
//会将信号量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(myQueue, ^{
NSLog(@"第三次任务开始_%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
NSLog(@"第三次任务结束_%@",[NSThread currentThread]);
//会将信号量的值加一
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"end_%@",[NSThread currentThread]);
}
start_{number = 1, name = main}
第一次任务开始_{number = 6, name = (null)}
第一次任务结束_{number = 6, name = (null)}
第二次任务开始_{number = 6, name = (null)}
第二次任务结束_{number = 6, name = (null)}
第三次任务开始_{number = 6, name = (null)}
第三次任务结束_{number = 6, name = (null)}
end_{number = 1, name = main}
-
dispatch_semaphore_create
创建信号量,初始值不能小于0 -
dispatch_semaphore_wait
等待降低信号量,也就是信号量-1 -
dispatch_semaphore_signal
提高信号量,也就是信号量+1 -
dispatch_semaphore_wait
和dispatch_semaphore_signal
通常配对使用
主要作用:
- 保持线程同步,将异步执行任务转换为同步执行任务
- 保证线程 安全,为线程加锁