目录
一,dispatch_after
二,dispatch_once
三,dispatch_apply
四,dispatch_group
五,dispatch_semaphore
六,dispatch_barrier
一,dispatch_after
1,使用
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"2");
});
NSLog(@"3");
}
// 打印
07:04:14.185538+0800 Demo[82191:12753573] 1
07:04:14.186943+0800 Demo[82191:12753573] 3
07:04:17.185982+0800 Demo[82191:12753573] 2
2,说明
-
它的作用是延迟执行任务
-
并不是在指定时间开始执行任务,而是在指定时间将任务添加到队列中
-
因为队列可能会出现阻塞的情况,所以任务的执行时间不一定准确
二,dispatch_once
1,使用
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 0; i < 5; i++) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"%d", i + 1);
});
}
}
// 打印
1
2,说明
-
它的作用是保证任务只执行一次
-
它能够保证任务的执行是线程安全的
-
它常应用于单例模式
三,dispatch_apply
1,使用
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin");
NSArray *array = @[@"1", @"2", @"3"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(array.count, queue, ^(size_t index) {
NSLog(@"%@---%@", array[index], [NSThread currentThread]);
});
NSLog(@"end");
}
// 打印
begin
2---<NSThread: 0x6000019498c0>{number = 3, name = (null)}
3---<NSThread: 0x60000194a080>{number = 4, name = (null)}
1---<NSThread: 0x600001916100>{number = 1, name = main}
end
2,说明
-
它的作用是快速遍历一组数据,类似于
for
循环 -
for
循环是逐个进行遍历,而它能够在多个线程中同时遍历多个数据 -
它按指定的次数将任务添加到队列中,并等待所有的任务执行完毕才返回
四,dispatch_group
1,使用
dispatch_group_notify
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin---%@", [NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"group中的任务都已经执行完毕---%@", [NSThread currentThread]);
});
NSLog(@"end---%@", [NSThread currentThread]);
}
// 打印
begin---<NSThread: 0x60000289e800>{number = 1, name = main}
end---<NSThread: 0x60000289e800>{number = 1, name = main}
任务1---<NSThread: 0x6000028cc980>{number = 4, name = (null)}
任务3---<NSThread: 0x6000028c6040>{number = 3, name = (null)}
任务2---<NSThread: 0x6000028c2100>{number = 5, name = (null)}
group中的任务都已经执行完毕---<NSThread: 0x60000289e800>{number = 1, name = main}
dispatch_group_wait
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin---%@", [NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
sleep(1.0);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"group中的任务都已经执行完毕---%@", [NSThread currentThread]);
NSLog(@"end---%@", [NSThread currentThread]);
}
// 打印
begin---<NSThread: 0x6000029fcbc0>{number = 1, name = main}
任务2---<NSThread: 0x6000029a1780>{number = 6, name = (null)}
任务1---<NSThread: 0x60000298d400>{number = 7, name = (null)}
任务3---<NSThread: 0x6000029b3b40>{number = 4, name = (null)}
group中的任务都已经执行完毕---<NSThread: 0x6000029fcbc0>{number = 1, name = main}
end---<NSThread: 0x6000029fcbc0>{number = 1, name = main}
-
dispatch_group_enter
和dispatch_group_leave
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin---%@", [NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// group中的任务数+1
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
sleep(1.0);
// group中的任务数-1
dispatch_group_leave(group);
});
// group中的任务数+1
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
sleep(1.0);
// group中的任务数-1
dispatch_group_leave(group);
});
// group中的任务数+1
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
sleep(1.0);
// group中的任务数-1
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"group中的任务数为0---%@", [NSThread currentThread]);
});
NSLog(@"end---%@", [NSThread currentThread]);
}
// 打印
begin---<NSThread: 0x600002d960c0>{number = 1, name = main}
end---<NSThread: 0x600002d960c0>{number = 1, name = main}
任务1---<NSThread: 0x600002dfb100>{number = 7, name = (null)}
任务3---<NSThread: 0x600002ddbc40>{number = 4, name = (null)}
任务2---<NSThread: 0x600002dc3400>{number = 5, name = (null)}
group中的任务数为0---<NSThread: 0x600002d960c0>{number = 1, name = main}
2,说明
-
dispatch_group_wait
会阻塞当前线程 -
dispatch_group_enter
和dispatch_group_leave
的作用等同于dispatch_group_async
-
它常应用于多个接口都请求完毕后再刷新UI
五,dispatch_semaphore
1,使用
- 将异步执行任务转换为同步执行任务
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1---%@", [NSThread currentThread]);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1.0);
NSLog(@"2---%@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"3---%@", [NSThread currentThread]);
}
// 打印
1---<NSThread: 0x600002491080>{number = 1, name = main}
2---<NSThread: 0x6000024c0e80>{number = 5, name = (null)}
3---<NSThread: 0x600002491080>{number = 1, name = main}
- 控制线程的最大并发数
- (void)viewDidLoad {
[super viewDidLoad];
// 最大并发数为2
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
for (int i = 0; i < 10; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
sleep(1.0);
NSLog(@"%d---%@", i + 1, [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
}
// 打印(同时只打印两次)
06:43:09.900220+0800 Demo[26085:16867256] 1---<NSThread: 0x6000006e2140>{number = 6, name = (null)}
06:43:09.900238+0800 Demo[26085:16867255] 2---<NSThread: 0x6000006fff80>{number = 5, name = (null)}
06:43:10.903011+0800 Demo[26085:16867239] 3---<NSThread: 0x6000006e7900>{number = 3, name = (null)}
06:43:10.903022+0800 Demo[26085:16867243] 4---<NSThread: 0x6000006c7c40>{number = 8, name = (null)}
06:43:11.906306+0800 Demo[26085:16867240] 5---<NSThread: 0x6000006b8600>{number = 4, name = (null)}
06:43:11.906350+0800 Demo[26085:16867259] 6---<NSThread: 0x6000006c7f40>{number = 9, name = (null)}
06:43:12.907370+0800 Demo[26085:16867261] 7---<NSThread: 0x6000006c7f80>{number = 11, name = (null)}
06:43:12.907366+0800 Demo[26085:16867260] 8---<NSThread: 0x6000006cf140>{number = 10, name = (null)}
06:43:13.912833+0800 Demo[26085:16867262] 9---<NSThread: 0x6000006c7d00>{number = 13, name = (null)}
06:43:13.912925+0800 Demo[26085:16867263] 10---<NSThread: 0x6000006caac0>{number = 12, name = (null)}
- 把初始值设置为1,代表同一时间只允许一个线程访问资源,这样它就能起到锁的作用
@interface ViewController ()
@property (nonatomic, assign) int ticket;
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.ticket = 10;
self.semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self saleTicket];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self saleTicket];
}
});
}
- (void)saleTicket {
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
int oldTicket = self.ticket;
sleep(0.3);
oldTicket -= 1;
self.ticket = oldTicket;
NSLog(@"剩余%d张票---%@", self.ticket, [NSThread currentThread]);
dispatch_semaphore_signal(self.semaphore);
}
@end
// 打印
剩余9张票---<NSThread: 0x60000324a980>{number = 3, name = (null)}
剩余8张票---<NSThread: 0x600003253b80>{number = 5, name = (null)}
剩余7张票---<NSThread: 0x60000324a980>{number = 3, name = (null)}
剩余6张票---<NSThread: 0x600003253b80>{number = 5, name = (null)}
剩余5张票---<NSThread: 0x60000324a980>{number = 3, name = (null)}
剩余4张票---<NSThread: 0x600003253b80>{number = 5, name = (null)}
剩余3张票---<NSThread: 0x60000324a980>{number = 3, name = (null)}
剩余2张票---<NSThread: 0x600003253b80>{number = 5, name = (null)}
剩余1张票---<NSThread: 0x60000324a980>{number = 3, name = (null)}
剩余0张票---<NSThread: 0x600003253b80>{number = 5, name = (null)}
2,说明
dispatch_semaphore_wait
1>如果信号量的值大于0,就将值-1并往下执行
2>如果信号量的值等于0,就让线程休眠并等待信号
3>收到信号后会唤醒线程并重新判断信号量的值
dispatch_semaphore_signal
将信号量的值+1并发送信号
六,dispatch_barrier
1,使用
dispatch_barrier_async
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin---%@", [NSThread currentThread]);
__block int data = 99;
dispatch_queue_t queue = dispatch_queue_create("MyConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
sleep(1.0);
NSLog(@"读1---%d---%@", data, [NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(1.0);
NSLog(@"读2---%d---%@", data, [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
sleep(1.0);
data = 100;
NSLog(@"写---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(1.0);
NSLog(@"读3---%d---%@", data, [NSThread currentThread]);
});
dispatch_async(queue, ^{
sleep(1.0);
NSLog(@"读4---%d---%@", data, [NSThread currentThread]);
});
NSLog(@"end---%@", [NSThread currentThread]);
}
// 打印
07:23:15.929766+0800 Demo[34756:17878123] begin---<NSThread: 0x60000392ddc0>{number = 1, name = main}
07:23:15.930049+0800 Demo[34756:17878123] end---<NSThread: 0x60000392ddc0>{number = 1, name = main}
07:23:16.932491+0800 Demo[34756:17878203] 读1---99---<NSThread: 0x6000039719c0>{number = 3, name = (null)}
07:23:16.932491+0800 Demo[34756:17878195] 读2---99---<NSThread: 0x60000396a280>{number = 5, name = (null)}
07:23:17.938203+0800 Demo[34756:17878195] 写---<NSThread: 0x60000396a280>{number = 5, name = (null)}
07:23:18.940880+0800 Demo[34756:17878203] 读4---100---<NSThread: 0x6000039719c0>{number = 3, name = (null)}
07:23:18.940883+0800 Demo[34756:17878195] 读3---100---<NSThread: 0x60000396a280>{number = 5, name = (null)}
dispatch_barrier_sync
dispatch_barrier_sync(queue, ^{
sleep(1.0);
data = 100;
NSLog(@"写---%@", [NSThread currentThread]);
});
// 打印
07:29:57.114729+0800 Demo[34807:17881597] begin---<NSThread: 0x600003e71580>{number = 1, name = main}
07:29:58.120079+0800 Demo[34807:17881637] 读1---99---<NSThread: 0x600003e4ed00>{number = 4, name = (null)}
07:29:58.120099+0800 Demo[34807:17881639] 读2---99---<NSThread: 0x600003e16a80>{number = 7, name = (null)}
07:29:59.121744+0800 Demo[34807:17881597] 写---<NSThread: 0x600003e71580>{number = 1, name = main}
07:29:59.122171+0800 Demo[34807:17881597] end---<NSThread: 0x600003e71580>{number = 1, name = main}
07:30:00.124470+0800 Demo[34807:17881637] 读4---100---<NSThread: 0x600003e4ed00>{number = 4, name = (null)}
07:30:00.124501+0800 Demo[34807:17881639] 读3---100---<NSThread: 0x600003e16a80>{number = 7, name = (null)}
dispatch_barrier_async_and_wait
dispatch_barrier_async_and_wait(queue, ^{
sleep(1.0);
data = 100;
NSLog(@"写---%@", [NSThread currentThread]);
});
// 打印
10:20:10.414882+0800 Demo[35536:17905685] begin---<NSThread: 0x60000084ccc0>{number = 1, name = main}
10:20:11.421195+0800 Demo[35536:17905758] 读2---99---<NSThread: 0x60000080d0c0>{number = 4, name = (null)}
10:20:11.421212+0800 Demo[35536:17905764] 读1---99---<NSThread: 0x600000813100>{number = 3, name = (null)}
10:20:12.422726+0800 Demo[35536:17905685] 写---<NSThread: 0x60000084ccc0>{number = 1, name = main}
10:20:12.423153+0800 Demo[35536:17905685] end---<NSThread: 0x60000084ccc0>{number = 1, name = main}
10:20:13.423888+0800 Demo[35536:17905758] 读4---100---<NSThread: 0x60000080d0c0>{number = 4, name = (null)}
10:20:13.423965+0800 Demo[35536:17905764] 读3---100---<NSThread: 0x600000813100>{number = 3, name = (null)}
2,说明
- 执行顺序
1>先同时执行在
dispatch_barrier
函数前添加的任务2>再单独执行在
dispatch_barrier
函数中添加的任务3>然后同时执行在
dispatch_barrier
函数后添加的任务
- 对比
1>
dispatch_barrier_async
:异步执行2>
dispatch_barrier_sync
:同步执行,会阻塞当前线程3>
dispatch_barrier_async_and_wait
:同步执行,会阻塞当前线程
-
不能用全局并发队列,否则
dispatch_barrier
会失效 -
它常应用于“多读单写”的场景
网友评论