1.多任务请求接口,完成后,在刷新数据,常用方法

2018年07月18日 16:34:38 hbblzjy 阅读数:1382

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hbblzjy/article/details/81100453

//线程组解决同一个界面需要请求多个接口数据,当全部请求完成后,再进入主线程刷新界面

/*

这种问题使用 dispatch_group_enter(grpupE);来解决,dispatch_group_enter 和 dispatch_group_leave 必须要成对出现;

dispatch_group_enter : 使用一种手动的方式将另外一个 block 以不同于 dispatch_group_async 的方式添加到线程组中。在异步任务开始之前调用;

dispatch_group_leave : 手动指示一个 block 块执行完毕。以一种不用于 dispatch_group_async 的方式离开线程组,在异步任务执行完成之后调用;

如果不添加enter、leave,那么将会先执行完所有的外围方法操作,然后才会执行block中的内容,这样就无法实现数据全部完成后再刷新主界面的操作。其实这不难理解,比如block是在A方法中,block的执行,都是在A方法执行完后才会执行的

*/

//1、不开启子线程的线程组简化方式

dispatch_group_t group = dispatch_group_create();

//模拟网络请求1

dispatch_group_enter(group);

//实际运用时,用网络请求的方法代替下面的内容,不要忘记leave      异步

dispatch_async(dispatch_get_global_queue(0, 0), ^{

for (int i = 0; i < 5; i++) {

[NSThread sleepForTimeInterval:1];

NSLog(@"当前线程:%@,是否是主线程:%@...1111···%d",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否",i);//当前线程:<NSThread: 0x60000027ef40>{number = 3, name = (null)},是否是主线程:否...1111···0

}

dispatch_group_leave(group);

});

NSLog(@"当前线程:%@,是否是主线程:%@...4444···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x604000071d40>{number = 1, name = main},是否是主线程:是...4444···

//模拟网络请求2

dispatch_group_enter(group);

//实际运用时,用网络请求的方法代替下面的内容,不要忘记leave      异步

dispatch_async(dispatch_get_global_queue(0, 0), ^{

for (int i = 0; i < 5; i++) {

[NSThread sleepForTimeInterval:1];

NSLog(@"当前线程:%@,是否是主线程:%@...2222···%d",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否",i);//当前线程:<NSThread: 0x604000272540>{number = 4, name = (null)},是否是主线程:否...2222···0

}

dispatch_group_leave(group);

});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

NSLog(@"当前线程:%@,是否是主线程:%@...3333···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x604000071d40>{number = 1, name = main},是否是主线程:是...3333···

});

结果如图:

//2、开启子线程的线程组

//一个并发队列

dispatch_queue_t queueE = dispatch_queue_create("group.queue", DISPATCH_QUEUE_CONCURRENT);

//一个线程组

dispatch_group_t groupE = dispatch_group_create();

dispatch_group_async(groupE, queueE, ^{

NSLog(@"当前线程:%@,是否是主线程:%@...1111···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x60400026a540>{number = 3, name = (null)},是否是主线程:否...1111···

//模拟网络请求1

dispatch_group_enter(groupE);

//实际运用时,用网络请求的方法代替下面的内容,不要忘记leave      异步

dispatch_async(dispatch_get_global_queue(0, 0), ^{

for (int i = 0; i < 5; i++) {

[NSThread sleepForTimeInterval:1];

NSLog(@"当前线程:%@,是否是主线程:%@...2222···%d",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否",i);//当前线程:<NSThread: 0x60400026a540>{number = 3, name = (null)},是否是主线程:否...2222···0

}

dispatch_group_leave(groupE);

});

});

dispatch_group_async(groupE, queueE, ^{

NSLog(@"当前线程:%@,是否是主线程:%@...3333···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x60400026a900>{number = 4, name = (null)},是否是主线程:否...3333···

//模拟网络请求2

dispatch_group_enter(groupE);

//实际运用时,用网络请求的方法代替下面的内容,不要忘记leave      异步

dispatch_async(dispatch_get_global_queue(0, 0), ^{

for (int i = 0; i < 5; i++) {

[NSThread sleepForTimeInterval:1];

NSLog(@"当前线程:%@,是否是主线程:%@...4444···%d",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否",i);//当前线程:<NSThread: 0x60000026cac0>{number = 5, name = (null)},是否是主线程:否...4444···0

}

dispatch_group_leave(groupE);

});

});

dispatch_group_async(groupE, queueE, ^{

NSLog(@"当前线程:%@,是否是主线程:%@...5555···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x60000026cac0>{number = 5, name = (null)},是否是主线程:否...5555···

//模拟网络请求3

dispatch_group_enter(groupE);

//实际运用时,用网络请求的方法代替下面的内容,不要忘记leave      异步

dispatch_async(dispatch_get_global_queue(0, 0), ^{

for (int i = 0; i < 5; i++) {

[NSThread sleepForTimeInterval:1];

NSLog(@"当前线程:%@,是否是主线程:%@...6666···%d",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否",i);//当前线程:<NSThread: 0x60400026a900>{number = 4, name = (null)},是否是主线程:否...6666···0

}

dispatch_group_leave(groupE);

});

});

//    dispatch_group_notify(groupE, queueE, ^{

//        NSLog(@"当前线程:%@,是否是主线程:%@...7777···",[NSThread currentThread],[NSThread isMainThread]?@"":@"");//当前线程:<NSThread: 0x60400026a540>{number = 3, name = (null)},是否是主线程:否...7777···

//        dispatch_async(dispatch_get_main_queue(), ^{

//            NSLog(@"当前线程:%@,是否是主线程:%@...8888···",[NSThread currentThread],[NSThread isMainThread]?@"":@"");//当前线程:<NSThread: 0x604000069700>{number = 1, name = main},是否是主线程:是...8888···

//        });

//    });

//简化上一种形式

dispatch_group_notify(groupE, dispatch_get_main_queue(), ^{

NSLog(@"当前线程:%@,是否是主线程:%@...7777···",[NSThread currentThread],[NSThread isMainThread]?@"是":@"否");//当前线程:<NSThread: 0x604000071d40>{number = 1, name = main},是否是主线程:是...7777···

});

结果如图:

当取消了enter和leave语句后:

版权所有,转载请注明出处,谢谢~~~不喜勿喷!谢谢

【多线程】多个请求完成以后再执行其他操作

大基本功 关注

2018.06.19 14:46 字数 62 阅读 24评论 0喜欢 0

有时会出现这样一种情况,比如某个页面需请求多个接口获取数据后刷新UI界面,直接上代码使用GCD完成

1.完成数据后回调

- (void)getAdHotTopDataBaseRequestisScu:(void(^)(BOOL isScu))requestisScu{

WEAKBLOCK;

[self.topAddArray removeAllObjects];

NSString *urlStr = @"Ad/fx_top";

[LFNetWorkManager requestDataBaseWithURLByGET:urlStr parameters:nil isWithToken:NO completed:^(id responseObject) {

if([responseObject[@"code"] integerValue] == 200){

[ToosZFJ readAndWriteHomeListDataBase:responseObject fileName:[urlStr stringFromMD5] completed:nil];//这个是我写的缓存数据的方法

NSArray *data = responseObject[@"data"];

for (NSDictionary *dict in data) {

ADModel *model = [[ADModel alloc]init];

[model setValuesForKeysWithDictionary:dict];

model.mid = dict[@"id"];

if([dict[@"circle"] integerValue] == 1){

//话题

}else{

//头部轮播广告

[weakSelf.topAddArray addObject:model];

}

}

}else{

[weakSelf SHOWPrompttext:responseObject[@"message"]];

}

if(requestisScu){

requestisScu((200 == [responseObject[@"code"] integerValue])?YES:NO);

}

}];

}

2.发起异步请求并监听

- (void)startAllRequest{

[self showMBProgressHUDLoding:nil];

dispatch_group_t group = dispatch_group_create();

dispatch_queue_t queue= dispatch_get_global_queue(0, 0);

// 广告数组

dispatch_group_enter(group);

dispatch_group_async(group, queue, ^{

[self getAdHotTopDataBaseRequestisScu:^(BOOL isScu) {

dispatch_group_leave(group);

}];

});

// 我的关注

dispatch_group_enter(group);

dispatch_group_async(group, queue, ^{

[self getDataOfSOurcesFoucesRequestisScu:^(BOOL isScu) {

dispatch_group_leave(group);

}];

});

// 推荐比赛

dispatch_group_enter(group);

dispatch_group_async(group, queue, ^{

[self getDataSourcesCompareRequestisScu:^(BOOL isScu) {

dispatch_group_leave(group);

}];

});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

[weakSelf RemoveMBProgressHUDLoding:nil];

[weakSelf.collectionView reloadData];

[weakSelf endRefreshingForTableView:weakSelf.collectionView];

});

}

2.多任务,请求数据,完成后的第二种方法,  简单美姊姊

使用第三方库来实现

https://www.cnblogs.com/sundaysgarden/articles/10365574.html

3.使用dispatch_semaphore_t控制多个线程使用系统资源

iOS GCD中级篇 - dispatch_semaphore(信号量)的理解及使用

理解这个概念之前,先抛出一个问题

问题描述:

假设现在系统有两个空闲资源可以被利用,但同一时间却有三个线程要进行访问,这种情况下,该如何处理呢?

或者

我们要下载很多图片,并发异步进行,每个下载都会开辟一个新线程,可是我们又担心太多线程肯定cpu吃不消,那么我们这里也可以用信号量控制一下最大开辟线程数。

定义:

1、信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理,则可告知系统按照我们指定的信号量数量来执行多个线程。

其实,这有点类似锁机制了,只不过信号量都是系统帮助我们处理了,我们只需要在执行线程之前,设定一个信号量值,并且在使用时,加上信号量处理方法就行了。

2、信号量主要有3个函数,分别是:

1

2

3

4

5

6

7

8

//创建信号量,参数:信号量的初值,如果小于0则会返回NULL

dispatch_semaphore_create(信号量值)

//等待降低信号量

dispatch_semaphore_wait(信号量,等待时间)

//提高信号量

dispatch_semaphore_signal(信号量)

  

注意,正常的使用顺序是先降低然后再提高,这两个函数通常成对使用。 (具体可参考下面的代码示例) 

3、那么就开头提的问题,我们用代码来解决

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

-(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);

});

}

执行结果:

  

总结:由于设定的信号值为2,先执行两个线程,等执行完一个,才会继续执行下一个,保证同一时间执行的线程数不超过2。

这里我们扩展一下,假设我们设定信号值=1

1

dispatch_semaphore_create(1)<br><br>

那么结果就是:

如果设定信号值=3

1

dispatch_semaphore_create(3)<br><br>

那么结果就是:

其实设定为3,就是不限制线程执行了,因为一共才只有3个线程。

以上只是举的比较简单的例子,在一些特殊场景下,合理利用信号量去控制,能够方便的解决我们的难题哦

4. NSOperationQueue

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 设置最大线程数
queue.maxConcurrentOperationCount = 5;
// 创建一个A操作 NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i<10; i++) {
NSLog(@"i的值是:%d",i);
}
}]; // 创建一个B操作 NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{ for (int j = 0; j<20; j++) { NSLog(@"j的值是:%d",j); } }]; // 添加依赖 B要在A打印完在进行打印 所以是B依赖于A 那么只需要添加如下代码即可完成 [operationB addDependency:operationA]; // 分别加入到队列中 [queue addOperation:operationA]; [queue addOperation:operationB]; //YES会阻塞当前线程
// [queue addOperations:@[operationA, operationB] waitUntilFinished:NO];

作者:一叶倾城乱
链接:https://www.jianshu.com/p/56f4f2cf8cae
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS开发之线程组解决请求多个接口数据,完成后,再刷新界面的更多相关文章

  1. java异步线程池同时请求多个接口数据

    一.主要使用类 . ExecutorService java线程池类 申明方式:ExecutorService exc = Executors.newFixedThreadPool(requestPa ...

  2. React在componentWillMount中请求接口数据结束后再执行render

    1.在getInitialState中初始化isloading,初始值false getInitialState() { return { editionid: '', isloading:false ...

  3. 使用Jquery解决Asp.Net中下拉列表值改变后访问服务器刷新界面。

    使用DropDownList控件时,改变选项时,获取服务端数据库数据并刷新界面数据. 1. 绑定DropDownList控件SelectedIndexChanged事件. 2. AutoPortBac ...

  4. 【iOS系列】-iOS开发,GET,POST请求使用

    [iOS系列]-iOS开发,GET,POST请求使用 步骤: 1:实例化URL(网络资源) 2:根据URL建立URLRequest(网络请求) 默认为GET请求: 对于POST请求,需要创建请求的数据 ...

  5. iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

    iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目文件结构和plist文件 二.实现效果 三.代码示例 1.没有使用配套的类,而是直接使用xib文 ...

  6. IOS开发使用委托delegate在不同窗口之间传递数据

    IOS开发使用委托delegate在不同窗口之间传递数据是本文要介绍的内容,主要是来讲解如何使用委托delegate在不同窗口之间传递数据,具体内容来看详细内容.在IOS开发里两个UIView窗口之间 ...

  7. php curl请求和获取接口数据

    curl请求和获取接口数据 class ToolModel{ /** * [http 调用接口函数] * @Author GeorgeHao * @param string $url [接口地址] * ...

  8. IOS开发之自动布局显示网络请求内容

    在上一篇博客中详细的介绍了IOS开发中的相对布局和绝对布局,随着手机屏幕尺寸的改变,在App开发中为了适应不同尺寸的手机屏幕,用自动布局来完成我们想要实现的功能和效果显得尤为重要.本人更喜欢使用相对布 ...

  9. iOS开发之线程间的MachPort通信与子线程中的Notification转发

    如题,今天的博客我们就来记录一下iOS开发中使用MachPort来实现线程间的通信,然后使用该知识点来转发子线程中所发出的Notification.简单的说,MachPort的工作方式其实是将NSMa ...

随机推荐

  1. django数据查询之F查询和Q查询

    仅仅靠单一的关键字参数查询已经很难满足查询要求.此时Django为我们提供了F和Q查询: # F 使用查询条件的值,专门取对象中某列值的操作 # from django.db.models impor ...

  2. c/c++ 标准顺序容器 容器的访问,删除 操作

    c/c++ 标准顺序容器 容器的访问,删除 操作 pop_front:vector,string不支持 pop_back:forward_list不支持 知识点 1,front, back, at 成 ...

  3. SpringBoot实现热部署(修改class不需要重启)

    热部署: devtools可以实现页面热部署(即页面修改后会立即生效, 这个可以直接在application.properties文件中配置spring.thymeleaf.cache=false来实 ...

  4. [Hive_3] Hive 建表指定分隔符

    0. 说明 Hive 建表示例及指定分隔符 1. Hive 建表 Demo 在 Hive 中输入以下命令创建表 user2 create table users2 (id int, name stri ...

  5. python——虚拟环境之virtualenvwrapper-win(windows10,64位)

    1 问题描述 当M个项目需要N个版本的python环境配置时(M>N)时,我们没有必要对每个项目都创建一个虚拟环境,只需要创建N个虚拟环境即可.这样节省了大量存储空间(特别是当M远大于N时).但 ...

  6. spring cloud 微服务日志跟踪 sleuth logback elk 整合

    看过我之前的文章的就可以一步一步搭建起日志传输到搜索引擎 不知道的 看下之前的文章 (1) 记一次logback传输日志到logstash根据自定义设置动态创建ElasticSearch索引 (2)关 ...

  7. February 13th, 2018 Week 7th Tuesday

    You are your greatest asset. 你就是你自己最大的资本. For most of us, there are few things that we can count on ...

  8. Metasploit渗透测试梗概

    1.渗透测试基础内容 https://blog.csdn.net/Fly_hps/article/details/79492646 2.Metasploit基础 https://blog.csdn.n ...

  9. 并发的HashMap为什么会引起死循环?

    转载:http://blog.csdn.net/zhuqiuhui/article/details/51849692 今天研读Java并发容器和框架时,看到为什么要使用ConcurrentHashMa ...

  10. 如何弄清Linux系统运行何种系统管理程序

    如何弄清Linux系统运行何种系统管理程序 虽然我们经常听到系统管理器System Manager这词,但很少有人深究其确切意义.现在我们将向你展示其区别. 我会尽自己所能来解释清楚一切.我们大多都知 ...