Android_Question
Android_Question copied to clipboard
记录2019年社招面试过程中的一些问题,供大家参考,可以补充和指正,一起成长~
时间有点长了,我的问题描述可能有些不太准确,但是考点就是future实现。 相关知识可以看:[https://www.jianshu.com/p/949d44f3d9e3](https://www.jianshu.com/p/949d44f3d9e3)
利用LinketHashMap数组的有序性和键的唯一性来处理: ``` private void printChar(String source) { if (source == null) { return; } String soureTrim = source.replaceAll(" ", "");//去掉字符串中的所有空格 char[] chars = soureTrim.toCharArray();//拿到字符串对应的char[] int length = chars.length; //用map键的唯一性去处理记录重复数据,而选择LinkedHashMap是为了保证有序 LinkedHashMap...
- sleep是Thread的静态方法;wait是Object中的方法; - sleep过程中不会释放锁,不会让出系统资源;wait会释放锁资源,将其放入等待池中,让出系统资源,让cpu可以执行其他线程; - sleep之后可以主动释放锁;wait需要手动去notify;
- sw(smallestWidth最小宽度)适配; - 通过修改系统的density值进行适配;
- AsyncTask内部封装了两个线程池和一个Handler。两个线程池作用分别是:用于任务队列的线程池和用于执行的线程池。执行线程池的核心线程数是2-4之间,也取决于cpu核数,最大线程数是2*cup核数,线程队列定义的是128。而Handler的作用主要是进行线程间通信。 一个AsyncTask对象只能被执行一次,也就是只能调用一次execute,否则会抛异常。 而AsyncTask的任务队列通过synchronized关键字实现的是串行执行。而且由于AsyncTask内部线程池定义成了静态变量,所以整个进程的所有asyncTask全部都在这个串行线程池中排队执行,而且执行都使用同一个线程池,因此,在任务量较多时,效率不高,不建议使用。 - AsyncTask中的Handler是静态全局变量,而且还在handleMessage方法中获取了主线程的Looper为了能够进行线程间切换,所以就要求Handler对象在主线程中创建,execute方法必须在主线程执行。由于静态成员变量,会随着类的加载而加载,因此就需要AsyncTask在主线程中加载。(Android4.1及以上已有系统完成主线程加载,是在ActivityThread的main方法中调用了AsyncTask的init方法,就满足了类在主线程中加载。)
类加载分类: BootstrapClassLoader(负责加载java_home中的jre/lib/rt.jar中的class,不是ClassLoader的子类) ExtensionClassLoader(负责加载java平台中扩展的一些jar中的class) AppClassLoader(负责加载classpath中指定的jar或class文件) CustomClassLoader(自定义的classloader) JVM的类加载机制采用的是双亲委派模型。  类加载过程: 由底层类加载器开始查找是否已经加载,如果底层已经加载,则视为已经加载,上层就无需再加载,避免重复加载。如果没有加载,则向上层类加载器查找,以此类推,直到顶层类加载器。如果最后发现顶层类加载器也没有加载,则先交由顶层类加载器尝试加载,如果无法加载,则交由下层类加器加载,直至底层类加载器,如果还是无法加载,则JVM会抛出相应的类加载异常。
ButterKnife采用的是编译时注解,在编译时生成辅助类,在运行时通过辅助类完成操作。编译时注解运行效率较高,不需要反射操作。 XUtils采用的是运行时注解,在运行时通过反射进行操作。运行时注解相对效率较低。 Retrofit与EventBus采用的都是运行时注解,也就是通过反射技术处理的。
Handler机制如何保证消息不错乱?消息延迟是如何实现的?Handler、Looper、MessageQueue三者对应关系?内存泄漏如何避免?Looper中的死循环为什么不会引器主线程ANR?
 第一点:IO是面向流的,NIO是面向缓冲区的。 IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。 NIO是面向缓存的。数据读取到一个缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且要确保当更多的数据读入缓冲区时,不要覆盖缓冲区中未处理的数据。 第二点:IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情。NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,在数据可读之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。