面试题之--腾讯某面试题分析

作者: 继续向前冲 | 来源:发表于2017-02-01 21:39 被阅读595次

    本来春节前豪言壮语要看好多书,写好多博客,可惜假期已过半,但是觉得自己啥都没有搞,弄了半天这才是第一篇博客,看来要继续加快更新学习速度啦!!! 春节后第一篇先扒一扒面试题,觉得面试中也是内有乾坤,还是可以搞一搞的

    出租屋里下一步布置计划

    网上随便找的腾讯某年某月某次面试题,整理一下,留着备用

    一、autorelease嵌套原理 系统怎么处理的

    万语千言不如直接上代码

    #import <Foundation/Foundation.h>  
    #import "MyCar.h”  
    int main(int argc, const charchar * argv[]) {  
        MyCar *p1=[MyCar new];  
     @autoreleasepool {  
        @autoreleasepool {  
         [p1 autorelease];  
       }//在执行到此处时,p1被自动释放  此处可以自动释放无问题 }  
        //以下代码有错误  
        @autoreleasepool {  
            [p1 autorelease];//此时p1被加入进来  
            @autoreleasepool {  
                [p1 autorelease];//被重复加载进来,但仍然同一个  
            }//此处,p1被自动释放了,所以第一次加进来的那个也被释放了,因为是同一个对象     
     }//所以此处在调用[p1 release];时就出现报错:野指针  
          
        return 0;  
    } 
    

    运行结果:person object 0x100202750 overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug

    二、ARC原理处理原理

    • 完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句
    • 只要还有一个强指针变量指向对象,对象就会保持在内存中

    三、MRC 或ARC 怎么破循环应用

    就是使用weak(弱引用)来打破环,使环消失

    __weak typeof(self) weakSelf = self;
    

    四、线程安全

    比较常用的
    关键字
    1)@synchronized(互斥锁)
    优点:使用@synchronized关键字可以很方便地创建锁对象,而且不用显式的创建锁对象。

    缺点:会隐式添加一个异常处理来保护代码,该异常处理会在异常抛出的时候自动释放互斥锁。而这种隐式的异常处理会带来系统的额外开销,为优化资源,你可以使用锁对象。

    // 实例类person
    Person *person = [[Person alloc] init];
    
    // 线程A
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [person personA];
            [NSThread sleepForTimeInterval:3]; // 线程休眠3秒
        }
    });
    
    // 线程B
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @synchronized(person) {
            [person personB];
        }
    });
    

    锁定的对象为锁的唯一标识,只有标识相同时,才满足互斥。如果线程B锁对象person改为self或其它标识,那么线程B将不会被阻塞。
    方法
    1)NSLock(互斥锁)

    // 实例类
    person Person *person = [[Person alloc] init];
     // 创建锁
     NSLock *myLock = [[NSLock alloc] init];
     // 线程A dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         [myLock lock];     [person personA];    
         [NSThread sleepForTimeInterval:5];
         [myLock unlock]; 
    }); 
    // 线程B dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    
     [myLock lock];   
     [person personB];     
     [myLock unlock]; 
    });
    

    锁定的对象为锁的唯一标识,只有标识相同时,才满足互斥。如果线程B锁对象person改为self或其它标识,那么线程B将不会被阻塞。
    同synchronized 关键字 这种情况容易造成死锁,不过也是比较简单的锁
    注意:锁定(lock)和解锁(unLock)必须配对使用

    2)NSRecursiveLock(递归锁)
    条件锁,递归或循环方法时使用此方法实现锁,可避免死锁等问题。
    3)NSConditionLock(条件锁)
    使用此方法可以指定,只有满足条件的时候才可以解锁。
    参考文档

    五、NSOperation可不可以停止

    • NSOperation有一个cancel方法可以取消单个操作
    [operation cancel];
    
    • NSOperationQueue的cancelAllOperations相当于队列中的每个operation调用了cancel方法,会取消队列里面全部的操作.
    • 但是,不能取消正在进行中的任务,队列调用了cancelAllOperations后会等当前正在进行的任务执行完闭后取消后面的操作
    • 最好可以经常通过判断isCancelled方法检测操作是否被取消,以响应外部可能进行的取消操作

    六、http状态码,自己写http框架,缓存,异步,并发高性能的解决方案

    用过的200 ok 204 No Content 400 Bad Request 404 Not Found 500 Internal Error, 503 Server Not Available

    状态码定义规则
    • 框架 基本上都是NSURLSession 来写开发网络层,主要是需要网络层和业务层不要混到一起,独立起来,封装成独立的方法,最好使用block比较清爽,例如骨灰级框架AFN 就是这样搞得, 使人用起来比较方便。
    • 异步,NSURLSession 都是异步的操作,如果有需要可以加入NSOperationQueue 控制一些流程
    • 缓存,除非有特殊要求,个人建议还是使用NSURLCache或者NSCache来完成。
    • 对于并发高性能:需要知道的是,NSURLSession在iOS中最多可以有4个tasks同时运行,所以应该复用所创建的NSURLSession, 在它之上创建不同的tasks。如果像是tableview中加载图片,可以创建一个队列(queue), 如果tasks超过4个,把超过的放入这个队列中,当之前的任务完成时,检查队列中有没有等待的,如果有,把它们从队列中取出来,然后[task resume]
      参考文档
      注意事项

    七、断点续传方案

    可使用NSURLSession来完成. 主要通过以下的方法

    objective-c
      - (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler;
      - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
    
    如果不是使用NSURLSession, 则要麻烦一些,首先必需在暂停时记录下当前已接收的文件长度,在下一次开始时设置HTTP header里的Range:
    objective-c
    
        NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.receivedLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        ```
    ##八、UI,动画,动画优化方案,UITableViewCell优化方案
    UITableViewCell优化方案 
    1.使用系统机制的重用池来UITableViewCell
    2.减少subviews的数量
    3.减少动态添加控件,可以一起加载通过hidden 属性控制显隐
    **4.提前计算好好UITableViewCell的高度,最好在异步下载数据后就计算好并且缓存数据因为heightForRowAtIndexPath:函数是使用最频繁的
    5.最好直接绘制控件可以提高效率
    6.滑动时提前加载**
    
    ##九、本地数据库海量数据如何提高查询效率和存储效率
    查询的就此不展开啦,数据库这一块又是好大的一块,我也不是特别熟
     如何提高存储效率:
        1. 尽量避免在main thread中写数据
        2. 不要在Core Data中保存图片,文件等数据
        3. 对于删除,更新,尽量batch
        4. 注意调用[NSManagedObjectContext save:]的时机,尽量是由在后台运行的NSManagedObjectContext来完成写入。
    
    ##10:索引的缺点
    ***百度的***
    二、索引的特点
    
    1.索引可以加快数据库的检索速度
    
    2.索引降低了数据库插入、修改、删除等维护任务的速度
    
    3.索引创建在表上,不能创建在视图上
    
    4.索引既可以直接创建,也可以间接创建
    
    5.可以在优化隐藏中,使用索引
    
    6.使用查询处理器执行SQL语句,在一个表上,一次只能使用一个索引
    
    三、索引的优点
    
      1.创建唯一性索引,保证数据库表中每一行数据的唯一性
    
           2.大大加快数据的检索速度,这也是创建索引的最主要的原因
    
      3.加速表和表之间的连接特别是在实现数据的参考完整性方面特别有意义
    
      4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
    
      5.通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。
    
    四、索引的缺点
    
      1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
    
      2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大
    
      3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度

    相关文章

      网友评论

        本文标题:面试题之--腾讯某面试题分析

        本文链接:https://www.haomeiwen.com/subject/vrylittx.html