ios 多线程控制线程并发数、GCD之dispatch_group、GCD信号量
来源:互联网 发布:shop域名有发展吗 编辑:程序博客网 时间:2024/03/29 16:08
=======GCD信号量=====
假设现在系统有两个空闲资源可以被利用,但同一时间却有三个线程要进行访问,这种情况下,该如何处理呢?
我们要下载很多图片,并发异步进行,每个下载都会开辟一个新线程,可是我们又担心太多线程肯定cpu吃不消,那么我们这里也可以用信号量控制一下最大开辟线程数。
定义:
1、信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理,则可告知系统按照我们指定的信号量数量来执行多个线程。
其实,这有点类似锁机制了,只不过信号量都是系统帮助我们处理了,我们只需要在执行线程之前,设定一个信号量值,并且在使用时,加上信号量处理方法就行了。
2、信号量主要有3个函数,分别是:
//创建信号量,参数:信号量的初值,如果小于0则会返回NULL
dispatch_semaphore_create(信号量值)
//等待降低信号量
dispatch_semaphore_wait(信号量,等待时间)
//增加信号量
dispatch_semaphore_signal(信号量)
注意,正常的使用顺序是先降低然后再提高,这两个函数通常成对使用。
3、那么就开头提的问题,我们用代码来解决
-(void)dispatchSignal{
//crate的value表示,最多几个资源可访问
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任务1
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 1");
sleep(1);
NSLog(@"complete task 1");
dispatch_semaphore_signal(semaphore);
});<br>
//任务2
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 2");
sleep(1);
NSLog(@"complete task 2");
dispatch_semaphore_signal(semaphore);
});<br>
//任务3
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 3");
sleep(1);
NSLog(@"complete task 3");
dispatch_semaphore_signal(semaphore);
});
}
======GCD信号量测试2=====
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore =dispatch_semaphore_create(1);
NSMutableArray *array = [[NSMutableArrayalloc]init];
for (NSInteger i = 0; i < 100000; i++) {
dispatch_async(queue, ^{
/*
此时semaphore信号量的值如果 >= 1时:对semaphore计数进行减1,然后dispatch_semaphore_wait函数返回。该函数所处线程就继续执行下面的语句。
此时semaphore信号量的值如果=0:那么就阻塞该函数所处的线程,阻塞时长为timeout指定的时间,如果阻塞时间内semaphore的值被dispatch_semaphore_signal函数加1了,该函数所处线程获得了信号量被唤醒。然后对semaphore计数进行减1并返回,继续向下执行。如果阻塞时间内没有获取到信号量唤醒线程或者信号量的值一直为0,那么就要等到指定的阻塞时间后,该函数所处线程才继续向下执行。
执行到这里semaphore的值总是1
*/
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/* 因为dispatch_semaphore_create创建的semaphore的初始值为1,执行完上面的
dispatch_semaphore_wait函数之后,semaphore计数值减1会变为0,所以可访问array对象的线程只有1个,因此可安全地对array进行操作。
*/
[array addObject:[NSNumber numberWithInteger:i]];
/*
对array操作之后,通过dispatch_semaphore_signal将semaphore的计数值加1,此时semaphore的值由变成了1,所处
*/
dispatch_semaphore_signal(semaphore);
});
}
====GCD信号量测试4======
#import "ViewController.h"
typedef void(^FinishNetwork)();
@interface ViewController ()
@property (nonatomic,copy ) FinishNetwork block;
@property (nonatomic,copy ) NSString *string1;
@property (nonatomic,copy ) NSString *string2;
@property (nonatomic,copy ) NSString *string3;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[selfinitData];
}
- (void)initData {
// 创建信号量
dispatch_semaphore_t semaphore =dispatch_semaphore_create(0);
// 创建全局并行
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group =dispatch_group_create();
dispatch_group_async(group, queue, ^{
// 请求一
//这里通过 block表示请求结束,并标记一个信号量
[selfgetList1:^{
dispatch_semaphore_signal(semaphore);
}];
});
dispatch_group_async(group, queue, ^{
// 请求二
[selfgetList2:^{
dispatch_semaphore_signal(semaphore);
}];
});
dispatch_group_async(group, queue, ^{
// 请求三
[selfgetList3:^{
dispatch_semaphore_signal(semaphore);
}];
});
dispatch_group_notify(group, queue, ^{
//在这里进行请求后的方法
NSLog(@"string1:___%@",_string1);
NSLog(@"string2:___%@",_string2);
NSLog(@"string3:___%@",_string3);
// 三个请求对应三次信号等待
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
});
}
- (void)getList1:(FinishNetwork)block {
NSLog(@"加载列表1");
self.string1 =@"加载列表1";
}
- (void)getList2:(FinishNetwork)block {
NSLog(@"加载列表2");
self.string2 =@"加载列表2";
}
- (void)getList3:(FinishNetwork)block {
NSLog(@"加载列表3");
self.string3 =@"加载列表3";
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
参考:http://www.cnblogs.com/breezemist/p/5667776.html
dispatch_group_async,是用于同步工作的,但是,它的判断标准是放入的block是否执行完毕,如果我们放入block中包含异步的网络请求,这个方法无法在网络数据返回后再进行同步。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURLSession *session = [NSURLSession sharedSession];
dispatch_queue_t dispatchQueue = dispatch_queue_create("test.queue",DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t dispatchGroup = dispatch_group_create();
// dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
dispatch_group_enter(dispatchGroup);
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
NSLog(@"got data from internet1");
dispatch_group_leave(dispatchGroup);
}];
[task resume];
// });
// dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
dispatch_group_enter(dispatchGroup);
NSURLSessionDataTask *task2 = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
NSLog(@"got data from internet2");
dispatch_group_leave(dispatchGroup);
}];
[task2 resume];
// });
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
NSLog(@"end");
});
}
看正确是输出结果:
2016-07-13 17:46:10.282 aaaa[4847:300370] got data from internet1
2016-07-13 17:46:10.501 aaaa[4847:300370] got data from internet2
2016-07-13 17:46:10.502 aaaa[4847:300341] end
- ios 多线程控制线程并发数、GCD之dispatch_group、GCD信号量
- GCD编程-控制线程最大并发量之信号量
- GCD--信号量控制队列并发数
- iOS开发之GCD -- dispatch_group
- GCD信号量控制并发
- iOS之利用GCD信号量控制并发网络请求
- iOS之利用GCD信号量控制并发网络请求
- iOS --- GCD 信号量控制并发 (dispatch_semaphore)
- iOS GCD 之dispatch_group方面的开发
- iOS之GCD再谈(dispatch_group,dispatch_semaphore)
- iOS GCD之dispatch_group的使用(多个文件并发上传)
- 多线程并发控制dispatch_group
- GCD 并发数控制方案
- iOS--GCD(使用dispatch_group来进行线程同步)
- ios多线程学习之GCD线程锁
- iOS多线程之线程安全和GCD
- GCD(dispatch_group)
- GCD-dispatch_group
- ES6入门之Symbol
- 2017.09.06 界面显示与 dsp升级
- 使用nginx做load balance
- jetty JSP support not configured
- poj 2186 (tarjan 缩点)
- ios 多线程控制线程并发数、GCD之dispatch_group、GCD信号量
- 一个竞赛蒟蒻,开个Blog玩玩
- AAC音频编码库FAAC和解码库FAAD移植
- node封装mysql操作
- 0906 JSP的表达式语言EL
- 创建私有CA及证书颁布详解
- 这就是别人学习高效的原因
- NYOJ 225 小明求素数积
- nyoj860又见01背包