Android经典面试题(2017)

来源:互联网 发布:物流网络平台 编辑:程序博客网 时间:2024/06/05 10:09

synchronized函数和synchronized代码块的区别

  1. 首先synchronized函数和synchronized代码快的作用范围有区别,synchronized函数一般锁定的是当前类对象,synchronized代码块锁定作用域可以选择是本对象,也可以是字符串等等.
  2. 当前类对象锁没有释放的时候,本类的所有synchronized(this)同步代码块都阻塞。如果有并发请求synchronized函数,同一时间只能有一个请求执行 .
  3. 但是当前类对象锁没有释放的时候,其他请求可以访问本类中不带synchronized(this)的代码块,也可以访问非同一把锁的代码块例如synchronized(Str)等.
  4. 由于作用范围有区别,一般作用范围越小执行效率越高,平时开发中一般选择作用范围较小的synchronized.


如何判断一个对象是可以被回收的

  1. 之前java虚拟机使用引用计数器的算法,当引用计数器为0时代表该对象没有引用了然后被清理。但是这个方式很难解决循环引用问题,所以目前停止使用了。
  2. 目前用到的是可达性分析算法来确定一个对象是不是可以被回收。
  3. 原理是:通过一个叫GC Roots的对象当作根对象,然后开始向下搜索,搜索的路径叫做引用链,当对象到GC Roots没有任何引用链相连的时候,则证明此对象是不可用的.
  4. 不可用对象并不是马上就执行回收方法,执行清理方法之前至少要经历两次标记过程.
    ①如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。(即意味着直接回收).
    ②如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃.
  5. finalize()方法是对象回收前的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中不被回收,只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。
  6. 任何一个对象的finalize()方法都只会被系统自动调用一次,如果对象面临下一次回收,它的finalize()方法不会被再次执行,因此第二段代码的自救行动失败了。因为finalize()方法已经被虚拟机调用过,虚拟机都视为“没有必要执行”。(即意味着直接回收).


写一个函数,输入一个数如38,拆分 3 + 8 = 11,1 + 1 = 2,最后2无法拆分就返回

    public  int  getNum(int num) {        while (num >= 10) {            num = num / 10 + num % 10;        }        return num;    }


多个进程同时调用一个ContentProvider的query获取数据,ContentPrvoider是如何反应的呢?

分析:

我们知道Activity这样的组件,它生命周期的回调函数是在UI线程中执行的,ContentProvider的onCreate()方法也是在UI线程中运行的,回答这个问题前,我们首先要搞清楚ContentProvider的Query(),insert(),delete(),updata()这几个方法是否也是在UI线程中运行。

发现问题:

如果以上几个方法是在UI线程中运行的,那么多个线程并发去调用就很有可能出现ANR;如果不是在UI线程运行的,那它是在一个工作线程中运行的还是在多个线程中运行的呢?即ContentProvider是否支持并发操作呢?

分析问题:

ContentResolver与ContentProvider类隐藏了实现细节,但是ContentProvider所提供的Query(),insert(),delete(),updata()这几个方法都是在ContentProvider进行的线程池中运行的,而不是在进程的主线程中运行,以为这些方法有可能被多个地方调用,所以它们是线程安全的。
ContentProvider实现进程通信是依赖于Binder机制的,所以以上问题会回归到Binder线程处理问题,并不是每一个ContentProvider都会有一个线程池,而是一个进程共用一个线程池,共用的线程池就是Binder线程池。

标准答案:

一个content provider可以接受来自另外一个进程的数据请求。尽管ContentResolver与ContentProvider类隐藏了实现细节,但是ContentProvider所提供的query(),insert(),delete(),update()都是在ContentProvider进程的线程池中被调用执行的,而不是进程的主线程中。这个线程池是有Binder创建和维护的,其实使用的就是每个应用进程中的Binder线程池。



Android设计ContentProvider的目的是什么?

  1. 隐藏数据的实现方式,对外提供统一的数据访问接口;
  2. 更好的数据访问权限管理。ContentProvider可以对开发的数据进行权限设置,不同的URI可以对应不同的权限,只有符合权限要求的组件才能访问到ContentProvider的具体操作。
  3. ContentProvider封装了跨进程共享的逻辑,我们只需要Uri即可访问数据。由系统来管理ContentProvider的创建、生命周期及访问的线程分配,简化我们在应用间共享数据(进程间通信)的方式。我们只管通过ContentResolver访问ContentProvider所提示的数据接口,而不需要担心它所在进程是启动还是未启动。


运行在主线程的ContentProvider为什么不会影响主线程的UI操作?

  1. ContentProvider的onCreate()是运行在UI线程的,而query(),insert(),delete(),update()是运行在线程池中的工作线程的,所以调用这向个方法并不会阻塞ContentProvider所在进程的主线程,但可能会阻塞调用者所在的进程的UI线程!
  2. 所以,调用ContentProvider的操作仍然要放在子线程中去做。虽然直接的CRUD的操作是在工作线程的,但系统会让你的调用线程等待这个异步的操作完成,你才可以继续线程之前的工作。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 闲鱼正在退款中怎么办 拒收货物卖家拒绝退款怎么办 货物没问题淘宝卖家拒收怎么办 头发稀少长的慢怎么办 没满16岁怎么办银行卡 网上买东西手机号填错了怎么办 买东西电话号码填错了怎么办 淘宝联盟扣54分怎么办 联盟被扣54分怎么办 ofo押金退了余额怎么办 网购还没收货就已签收怎么办 理财公司倒闭分公司法人怎么办 公司让离职不想走怎么办 公司让离职自己不想走怎么办 小孩子有购物狂病怎么办 拉杆箱的轮子卡怎么办 想你了怎么办的英文 那现在怎么办 英文怎写 平安证券账号忘了怎么办 发现发票是假的怎么办 公司收到假发票入账了怎么办 手表皮带有汗味怎么办 利客来购物卡丢了怎么办 乐天玛特倒闭卡怎么办 lv皮带买长了怎么办 密袋鼠咬了人怎么办 lv皮带如果长了怎么办 天赐农场公众号进不去了怎么办 苹果删了订阅号怎么办 蚂蚁借呗没有自动扣款怎么办 有对方qq号名字怎么办 腾讯模拟器刺激现场注册上限怎么办 丹阳智慧人社登入密码忘了怎么办? ipad系统被锁了怎么办 电脑管理员账号删了怎么办 自己电脑删文件需要管理员怎么办 苹果电脑管理员密码忘记了怎么办 电脑提示安全设置不允许下载怎么办 微信和ipad同步怎么办 苹果6空间已满怎么办 苹果6内存虚满怎么办