以下是我的拙见,如有不当之处,欢迎大家指正!
一、在上一个网络请求的完成回调中调用写一个网络请求
这是一个最普通的思路,在上一个请求完成的回调中进行下一次的请求
二、利用NSOperation添加依赖操作和优先级
这个方法主要利用NSOperation
的addDependency:
方法来添加依赖
/// 操作(模拟网络请求)
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
[self network_request1];
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
[self network_request2];
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
[self network_request3];
}];
/// 添加依赖
[operation2 addDependency:operation1];
[operation3 addDependency:operation2];
/// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation1, operation2, operation3] waitUntilFinished:NO];
模拟网络请求
#pragma mark - Network
- (void)network_request1 {
sleep(3);
NSLog(@"-------- network request 1");
}
- (void)network_request2 {
sleep(2);
NSLog(@"-------- network request 2");
}
- (void)network_request3 {
sleep(1);
NSLog(@"-------- network request 3");
}
三、Dispatch_group 组队列
这个思路主要用到的方法有dispatch_group_enter
、dispatch_group_leave
、dispatch_group_wait
、dispatch_group_notify
在请求之前进入group
:“dispatch_group_enter
”
在请求之后离开group
:“dispatch_group_leave
”
group
内的任务为当前任务,所以这时候会卡住线程,等任务一执行完毕,这个类似信号量“dispatch_group_wait
”
注意:dispatch_group_enter 和dispatch_group_leave 成对出现,且在真实的网络请求环境中,请求成功或者失败都要leave
/// 创建组队列
self.group = dispatch_group_create();
/// 模拟网络请求
[self network_request1];
[self network_request2];
[self network_request3];
/// group 中任务全部完成
dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
NSLog(@"请求完成");
});
模拟网络请求
#pragma mark - Network
- (void)network_request1 {
/// 任务开始之前进入group
dispatch_group_enter(self.group);
sleep(3);
NSLog(@"-------- network request 1");
/// 任务完成,离开group,与 enter成对出现
dispatch_group_leave(self.group);
/// 现在 group 内的任务为当前任务,所以这时候会卡住线程,等任务一执行完毕,这个类似信号量
/// 注意 dispatch_group_leave 和 dispatch_group_enter 不能在同一个线程,不然会死锁
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)network_request2 {
/// 任务开始之前进入group
dispatch_group_enter(self.group);
sleep(2);
NSLog(@"-------- network request 2");
/// 任务完成,离开group,与 enter成对出现
dispatch_group_leave(self.group);
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)network_request3 {
/// 任务开始之前进入group
dispatch_group_enter(self.group);
sleep(1);
NSLog(@"-------- network request 3");
/// 任务完成,离开group,与 enter成对出现
dispatch_group_leave(self.group);
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
四、Dispatch_barrier 任务阻塞
主要方法dispatch_barrier_sync
和dispatch_barrier_async
相同点:都会等待方法之前的任务执行完,再执行方法后的任务
不同点:dispatch_barrier_sync
会等待自己的block中任务执行完在执行方法之后的任务,而dispatch_barrier_async
不会等待自己的任务结束,会继续执行后面的任务
/// 创建线程
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{
[self network_request1];
});
/// 阻塞当前线程
dispatch_barrier_sync(queue, ^{
NSLog(@"第一个请求完成");
});
dispatch_sync(queue, ^{
[self network_request2];
});
dispatch_barrier_sync(queue, ^{
NSLog(@"第二个请求完成");
});
dispatch_sync(queue, ^{
[self network_request3];
});
dispatch_barrier_sync(queue, ^{
NSLog(@"第三个请求完成");
});
模拟网络请求
#pragma mark - Network
- (void)network_request1 {
sleep(3);
NSLog(@"-------- network request 1");
}
- (void)network_request2 {
sleep(2);
NSLog(@"-------- network request 2");
}
- (void)network_request3 {
sleep(1);
NSLog(@"-------- network request 3");
}
五、Dispatch_semaphore 信号量
主要方法:dispatch_semaphore_signal
、dispatch_semaphore_wait
当信号量为0则该函数就会一直等待,也就是不返回(相当于阻塞当前线程),dispatch_semaphore_signal
我理解为订阅信号,会使得信号量+1
,dispatch_semaphore_wait
会使信号量-1
。当信号量不大于0时,信号量-1
,同时后续代码会继续执行,但是当信号量等于0时,信号量不做减1动作,同时阻塞当前的执行,在timeout之前遇到信号量大于0时,会继续做-1
操作,并执行后续任务。
/// 信号量 为 0,则该函数就会一直等待,也就是不返回(相当于阻塞当前线程)
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
/// 创建线程
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[self network_request1];
/// 请求完成订阅信号
dispatch_semaphore_signal(semaphore);
});
/// 等待信号
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
[self network_request2];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
[self network_request3];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
模拟网络请求
#pragma mark - Network
- (void)network_request1 {
sleep(4);
NSLog(@"-------- network request 1");
}
- (void)network_request2 {
sleep(2);
NSLog(@"-------- network request 2");
}
- (void)network_request3 {
// sleep(1);
NSLog(@"-------- network request 3");
}