有些时候需要控制异步执行的顺序
1 runLoop
-(void)runLoopTest{
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"A");
//RunLoop停止 并获取主线程
CFRunLoopStop(CFRunLoopGetMain());
}] ;
[task resume];
CFRunLoopRun();
NSLog(@"B");
}
2 dispatch_group_notify
-(void)gcdGroupTest{
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(@"A");
});
//通知执行完毕
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"B");
});
}
3 barrier 阻塞
-(void)dispath_barrier_asyncTest{
dispatch_queue_t queue = dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"A");
});
//barrier 阻塞
dispatch_barrier_async(queue, ^{
NSLog(@"拿到了A的值");
});
dispatch_async(queue, ^{
NSLog(@"B");
});
}
4 dependency
-(void)operationDependencyTest{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *p1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A");
}];
NSBlockOperation *p2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"B");
}];
NSBlockOperation *p3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"C");
}];
//p2 依赖p1
//p3 依赖p2
[p2 addDependency:p1];
[p3 addDependency:p2];
// waitUntilFinished是否阻塞当前线程
[queue addOperations:@[p1,p2,p3] waitUntilFinished:NO];
}
5 maxconCurrentOperationCount
-(void)maxConcurrentOperationCountTest{
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第1个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation1 isAsynchronous]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第2个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation2 isAsynchronous]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第3个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation3 isAsynchronous]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//设置最大任务数
queue.maxConcurrentOperationCount = 1;
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
6 信号量
-(void)testSemaphore{
/*
dispatch_semaphore_create 创建一个semaphore
dispatch_semaphore_signal 发送一个信号
dispatch_semaphore_wait 等待信号
简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。
*/
dispatch_group_t group = dispatch_group_create();//创建一个组
dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++){
//等待信号量
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//可以用生产者消费者的例子
//首先规定生产者/消费者1个物品
//生产者先生产5个物品 就是dispatch_semaphore_signal 释放5个物品
//之后消费者 就是dispatch_semaphore_wait 消费5个物品
//需要等待2秒之后 生产者才能生产5个物品给消费者 如此循环就行
/*
创建了一个初使值为10的semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了5个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为5的一个线程队列。
如果想让异步线程全部按照顺序执行 就把信号量设为1就行
*/
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
//释放信号量
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
7 优先级
-(void)priorityTest{
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第1个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation1 isAsynchronous]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第2个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation2 isAsynchronous]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是第3个任务在线程:%@执行,isMainThread: %d,isAync: %d",
[NSThread currentThread],
[NSThread isMainThread],
[operation3 isAsynchronous]);
}];
/*
设置操作对象的优先级,需要调用setQueuePriority:方法。优先级仅使用同一操作队列中的操作。
优先级级别不是依赖关系的替代品,优先级确定操作队列开始执行的顺序,只执行当前准备的操作。例如,如果队列中包含一个高优先级和一个低优先级的操作,并且两个操作都准备就绪,队列将首先执行高优先级的操作。如果高优先级操作没有 准备就绪 ,而低优先级的操作已经准备好,那么先执行低优先级操作。
优先级只影响操作执行的顺序,而不控制完成的顺序。而且并不是等待高优先级的队列执行完后再执行优先级低的队列。
其中总的来说是有两种因素
1 如果低优先级的任务已经准备好 高优先级的任务没有准备好 先执行低优先级的
2 优先级只是规定了执行顺序 而不是回调结果的顺序
*/
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
/*
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
*/
operation3.queuePriority = NSOperationQueuePriorityVeryHigh;
operation2.queuePriority = NSOperationQueuePriorityLow;
operation1.queuePriority = NSOperationQueuePriorityVeryLow;
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}