大数据压力的处理方案

当设计到大量数据的时候,比如说,直播的聊天。我们处理的时候,可以考虑三点:

  1. 分多次处理
  2. kCFRunLoopBeforeWaiting 闲时处理(在进入等待前,也就是说现在已经不忙了,才会要进入等待)
  3. 频率问题

代码如下:

#import "TwoLargeDataVC.h"

@interface TwoLargeDataVC (){
    
    CFRunLoopObserverRef observerRef;
}

@property (nonatomic, strong)IBOutlet UITableView *tableView;
@property (nonatomic, strong)NSMutableArray *dataArr;
@property (nonatomic, strong)NSMutableArray *newsDataArr;
@property (nonatomic, strong)NSLock *dataLock;

@end


/*
  被动接受数据()
 */

@implementation TwoLargeDataVC

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // 监听runloop状态 当runloop时候kCFRunLoopBeforeWaiting状态(开始等待前,即这个时候RunLoop已经不忙了),再来处理这个大数据量
    
    _dataArr = [NSMutableArray array];
    _newsDataArr = [NSMutableArray array];
    _dataLock = [NSLock new];

    _tableView.estimatedRowHeight = 0;
    _tableView.clipsToBounds = YES;
    [_tableView setFrame:CGRectMake(0, 300, _tableView.frame.size.width, 300)];
    
    [self runloopObserver];
    
    // 开启一个线程接收服务器的数据
    [NSThread detachNewThreadSelector:@selector(threadDataFromServer) toTarget:self withObject:nil];

}

/*
 1 分多次处理
 2 kCFRunLoopBeforeWaiting 闲时处理
 3 频率问题
 */

// 创建runloop 监听
- (void)runloopObserver{
    
    
    __weak typeof(self) weakSelf = self;
    __block NSTimeInterval timeInterVal = [[NSDate date] timeIntervalSince1970];
    // 创建观察者
    observerRef = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        
        // 设置刷新频率 最少0.5秒刷新一次
        //来处理数据量 (直播刷留言)
        if (activity == kCFRunLoopBeforeWaiting) { // 开始等待前,即这个时候RunLoop已经不忙了
            
            // 控制频率
            NSTimeInterval currentTimeInterVal = [[NSDate date] timeIntervalSince1970];
            // 小于0.5秒就直接返回,不进行后面的操作
            if (currentTimeInterVal - timeInterVal < 0.5) {
                return ;
            }
            timeInterVal = currentTimeInterVal;
            
            // 处理数据的时候要加上锁,保证数据安全
            [weakSelf.dataLock lock];
            NSArray *subArr = nil;
            if (weakSelf.newsDataArr.count > 0) { // 一次最多拿10条数据
                // 频率可以通过newsDataArr的数据量来控制(如果数据量大,频率就可以设置快一点,如果数据量小,就可以设置慢一点)
                NSRange range;
                if (weakSelf.newsDataArr.count >= 10) {
                    range = NSMakeRange(0, 10);
                }else{
                    range = NSMakeRange(0, weakSelf.newsDataArr.count-1);
                }
                // 拿出数据subArr
                subArr = [weakSelf.newsDataArr subarrayWithRange:range];
                // 将拿出的数据subArr从新数据中移除,避免下次还是会取到它
                [weakSelf.newsDataArr removeObjectsInRange:range];
                
            }
            
            // 将拿到的数据subArr添加到数据源中
            [weakSelf.dataArr addObjectsFromArray:subArr];
            [weakSelf.dataLock unlock];  // 数据操作结束,解锁
            [weakSelf.tableView reloadData]; // 刷新界面
            [weakSelf.tableView layoutIfNeeded];
            // 始终展示最后一页的数据,即最新的数据 tableView.contentSize.height 会每次都变大。所以ContentOffset的位置也要调整
            [weakSelf.tableView setContentOffset:CGPointMake(0, weakSelf.tableView.contentSize.height - weakSelf.tableView.frame.size.height)];
        }
        
    });
    // 添加观察者
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observerRef, kCFRunLoopCommonModes);
    
    
    
}

- (void)viewWillDisappear:(BOOL)animated{
    
    [super viewWillDisappear:animated];
    // 移除观察者
    CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observerRef, kCFRunLoopCommonModes);
    
}

// 接收服务器数据
- (void)threadDataFromServer{
    
    // 要注释了这个方法才会执行dealloc方法,因为下面是while(1),线程永远不会结束
    // 换成正常的网络请求,当请求结束,线程也就会结束的
    
    static int __countMsg = 0;
    while (1) {
        sleep(1);
        [_dataLock lock];
        for (int i = 0; i < random()%1000; i++) { // 生成1到999条不等的数据量

            __countMsg++;
            NSString *msgStr = [NSString stringWithFormat:@"%d---%ld", __countMsg, random()];
            [self.newsDataArr addObject:msgStr];
        }
        [_dataLock unlock];
        // 数据请求完成过后,要激活RunLoop来处理,这样才能将线程和RunLoop关联起来
        CFRunLoopWakeUp(CFRunLoopGetMain());
    }

}


#pragma mark - tableView delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
    return _dataArr.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    return 30;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.textLabel.text = _dataArr[indexPath.row];
    return cell;
}

- (void)dealloc{
    
    NSLog(@"%s", __func__);
}

@end

上面需要注意的是:

  1. 处理数据的时候,要加锁。避免数据出问题。
  2. 使用多线程请求数据的时候,当请求完成过后要唤醒主RunLoop
  3. 页面消失的时候,要移除观察者
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容