Android面试总结经

    自上周怒辞职以后,就开始苦逼的各种面试生涯,生活完全靠私活来接济,时有时没有,真难,还能快乐的玩耍吗,最多一天面试了5家,哎感觉都是不急招人,各种等待通知,好不容易等来一家,还克扣了薪资,从我要的12k到他们给8k,感觉累觉不爱。

     面试都是基本过了二面的,大到腾讯,阿里,百度,网易,小到15人的创业公司我都去了,难得今天休息一下,总结下面试经验,以便下次面试用到。技术题目我就不说了,这是基础,不会的还是把基础看下吧。后面的题目都是让人蛋疼的机制问题。

    1、什么是线程,线程和进程的区别,线程的工作原理

 线程就是程序执行流中最小单元,是系统独立调度的基本单位,线程不具有任何系统资源,这里需要特别注意,

就象程序一样,线程有生命周期:它们启动、执行,然后完成。一个程序或进程也许包含多个线程,而这些线程看来互相单独地执行。

线程是通过实例化Thread对象或实例化继承Thread的对象来创建的,但在对新的Thread对象调用start()方法之前,这个线程并没有开始执行。当线程运行到其run()方法的末尾或抛出未经处理的异常时,它们就结束了。

sleep()方法可以用于等待一段特定时间;而join()方法可能用于等到另一个线程完成。

线程的一些基本方法:

isAlive():判断线程是否还"活"着
   getPriority():
获得线程的优先级数值
   setPriority():
设置线程的优先级数值
   Thread.sleep():
将当前线程睡眠指定毫秒数
   join():
调用某线程的该方法,将当前线程与该线程"合并",即等待该线程结束,再恢复当前线程的运行
   yield():
让出cpu,当前线程进入就绪队列等待调度
   wait():
当前线程进入对象的wait pool
   notify()/notifyAll():
唤醒对象的wait pool中的一个/所有等待线程

特别注意sleep和wait的区别:

Wait是Object类的方法,范围是使该Object实例所处的线程。

Sleep()是Thread类专属的静态方法,针对一个特定的线程。

Wait方法使实体所处线程暂停执行,从而使对象进入等待状态,直到被notify方法通知或者wait的等待的时间到。Sleep方法使持有的线程暂停运行,从而使线程进入休眠状态,直到用interrupt方法来打断他的休眠或者sleep的休眠的时间到。

线程和进程的区别:

(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;

(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源

(3)线程是处理器调度的基本单位,但进程不是.

 

多线程

许多线程在执行中必须考虑与其他线程之间共享数据或协调执行状态。这就需要同步机制。在Java中每个对象都有一把锁与之对应。synchronized语句计算一个对象引用,试图对该对象完成锁操作, 并且在完成锁操作前停止处理。当锁操作完成synchronized语句体得到执行。当语句体执行完毕(无论正常或异常),解锁操作自动完成。作为面向对象的语言,synchronized经常与方法连用。一种比较好的办法是,如果某个变量由一个线程赋值并由别的线程引用或赋值,那么所有对该变量的访问都必须在某个synchromized语句或synchronized方法内。

2、如何去理解handlermessagemessagequeenlooper,一个message是否有几个looper,你写过looper没有。

1、MessageQueue:是一种数据结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。

2、Message:消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。

3、Looper

是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。

4、Handler

消息的处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。

3子线程和UI线程的区别,子线程的工作原理,如何更改UI

         这个比较简单一些,了解了上面的内容就知道子线程发送message,通过handler的handleMessage方法去获取message然后更新UI。

4遇到过OOM没有,举个你优化OOM的例子,

         Oom是指内存溢出,一般情况是图片过大造成的。解决方案:

(1)缓存图像到内存,采用软引用缓存到内存,而不是在每次使用的时候都从新加载到内存;

(2)调整图像大小,手机屏幕尺寸有限,分配给图像的显示区域本身就更小,有时图像大小可以做适当调整;

(3)采用低内存占用量的编码方式,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省内存;

(4)及时回收图像,如果引用了大量Bitmap对象,而应用又不需要同时显示所有图片,可以将暂时用不到的Bitmap对象及时回收掉;

(5)自定义堆内存分配大小,优化Dalvik虚拟机的堆内存分配;

5GC的工作原理

         Garbage Collection简称为GC,是垃圾回收的意思、内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃。Java语言提供的GC功能可以自动的检测对象是否超过作用域,从而达到自动回收内存的目的,java语言没有提供释放已分配内存的显示操作方法,资源回收工作全部交由GC来完成,程序员不能精确的控制垃圾回收的时机。

GC在实现垃圾回收时的基本原理:

Java的内存管理实际就是对象的管理,其中包括对像的分配和释放。对于程序员来说,分配对象使用new关键字,释放对象时只是将对象赋值为null,让程序员不能够再访问到这个对象,该对象被称为“不可达”。GC将负责回收所有“不可达”对象的内存空间。

对于GC来说,当程序员创建对象时,GC就开始监控这个对象地址、大小以及使用情况。通常GC采用有向图的方式记录并管理堆中的所有对象,通过这种方式确定哪些对象是“可达”的,哪些对象是“不可达”的。当GC确定一些对象为“不可达时”GC就有责任回收这些内存空间,但为了GC能够在不同的平台上实现,java规范对GC的很多行为都没有进行严格的规定。例如对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定,因此不同的JVM实现着不同的的实现算法,这也给JAVA程序员的开发带来了很多不确定性。

根据GC的工作原理,可以通过一些技巧和方式让GC运行更快,高效而又合理。编程建议如下:

1、尽早释放无用对象的引用,特别注意一些复杂对象,如数组,队列等。对于此类对象,GC回收它们的效率一般较低,如果程序允许,应尽早将不用的引用对象赋为null,这样可以加速GC的工作。

2、尽量少用finalize函数。finalize是java提供给程序员用来释放对象或资源的函数,但是它会加大GC的工作量,因此尽量少采用finalize函数回收资源。

6说下你的IPC通信的理解

Android系统中大量使用了基于C/S模式的通信方式。诸如短信操作,电话操作,视频音频捕获,传感器等都以服务(Service)的形式提供,并由相应的Server负责管理,应用程序作为Client只需要与这些Server建立连接并发送请求便能使用这些服务。因此,开发者完全不必关心Service的实现细节,直接与Server建立连接然后使用其提供的接口即可。Client和Server一般是运行在不同的进程中的,这就涉及到进程间通信(IPC,Inter-ProcessCommunication)。为了保证系统安全性,提高通信效率以及提供对C/S模式的支持,Android采用了一种基于共享内存的IPC机制——Binder机制。

具体的实现方法就是AIDL,这属于技术方面了,不懂的可以百度。

7httptcp通信的你做过什么项目

         http重点是url和httpclient。

状态码为1这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。

         状态码为2这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。

         状态码为3这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。

         状态码为4为错误码

         状态码为5服务器错误

 

         TCP重点就是sokect。

8复写过view吗?viewgourp里面有些什么方法?

         自定义view重要的是复写ondraw方法。

         View是继承viewgroup的,所以复写viewgroup能实现我们想要一切东西,viewgroup主要的方法:

         Onlayout()方法负责把该view放在参数指定位置。

         onMeasure()方法不但可以为ViewGroup指定大小,还可以通过遍历为每一个子View指定大小,在自定义ViewGroup中添加上面代码为ViewGroup中的每一个子View分配了显示的宽高。

         onDraw重绘view

         


Android面试总结经,布布扣,bubuko.com

Android面试总结经

上一篇:Windows 10应答文件


下一篇:iOS开发系列之二 - UILabel 用法小结