摘要:
- 线程安全的规约
- 造成OOM的分类
- 举一个例子说明如何优化内存
- 为什么不推荐使用Android Executors提供的创建线程池的方法
- 怎么保证一个APP的稳定性
- 哪些操作可以保证原子性
- 一个apk由哪几部分组成
- 安卓开发的过程中,你比较擅长哪方面
- await、wait、signal、signalAll、notify、notifyAll的区别
- 怎么去掉一个集合中重复的元素
- 使用HashMap在高并发需要注意什么问题
问题一
- 加锁会造成性能的开销,能用无锁数据结构,就不要用锁;能用锁区块,就不要用锁这个方法体;能用对象锁,就不用类锁
- 线程资源要用线程池提供,不允许自行显示创建线程
- 创建线程或线程池需要指定有意义的线程名称,方便出错时回溯
- 线程池不允许通过
Executors
去实现,而是通过ThreadPoolExecutor
的方式,避免资源耗尽的风险 SimgleDateFormat
是线程不安全的类,定义为static变量,必须加锁- 使用
Timer
运行多个TimeTask
,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledThreadPool
则没有这个问题 volatile
解决多线程一写多读的安全问题,没有解决多线程多写的安全问题,多写情况下推荐使用原子操作,比如:AtomicInteger
、AtomicLong
、AtomicBoolean
- 对多个资源、数据库表、对象加锁,需要保持一致的加锁顺序,否则可能出现死锁
问题二
内存溢出和Java虚拟机内存的划分有关,Java虚拟机划分为:方法区、堆、Java栈和本地方法栈,内存溢出分类为:
- 方法区内存溢出,抛出
OutOfMemoryError: PermGen space
- 堆内存溢出,抛出
OutOfMemoryError : java heap space
- Java栈内存溢出,抛出
:OutOfMemoryError:StackOverflowError
- 本地方法栈内存溢出,抛出
OutOfMemoryError: unable to create new native thread
- 内存抖动也会造成OOM。String拼接创建大量小的对象,导致内存碎片。当需要分配内存时,虽然总体上剩余的内存还是比较多的,但由于这些内存不连续,导致无法分配,系统直接返回OOM
https://blog.csdn.net/cp_panda_5/article/details/79613870
https://blog.csdn.net/nocol123/article/details/76223098
https://blog.csdn.net/wf_feng/article/details/82189215
问题三
项目中集成了LeakCanary
内存泄露检测工具,重点检查Activity和Fragment组件造成内存泄漏的位置,优化项目代码。
打开Android Profile内存动态窗口,重复打开和关闭某个界面,监听APP内存变化情况,Dump Java Heap
导出hprof文件,使用hprof-conv.exe
转换后,使用MAT内存分析工具打开,检查占用内存比较大的对象和相关的类。
在92回收启动界面引入一个单例,该单例持有LoadActivity.this
引用,LoadActivity设置了背景图片,跳转主界面后,LoadActivity无法被垃圾回收器回收造成内存泄露,同时背景图加载占据较大内存空间
Android 内存优化总结&实践
https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ
问题四
FixedThreadPool
和SingleThreadExecutor
允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM
CachedThreadPool
和ScheduleThreadPool
允许创建的线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM
问题五
- 开发阶段:多维度测试,单元测试,UI测试,功能测试,异常测试
- 开发阶段:优化内存,排查内存泄露,避免内存溢出
- 开发阶段:借助Lint工具(Inspect Code)、FindBugs工具优化代码和资源文件
- 发布阶段:APP加入完善的日志收集和上传功能,重点处理Crash问题
- 发布阶段:多维度监控,网络监控,流量监控,行为监控,性能监控
- 发布阶段:灰度发布,让一步用户下载安装,收集运行过程出现的问题
你的Android应用稳定吗?安卓App稳定性之旅
https://www.imooc.com/article/71846
App 稳定性测试方式
https://www.jianshu.com/p/6d4fe6bceee3
问题六
- 语句块或方法添加锁,保证多线程环境下的原子性
- Vector、CopyArrayList、ConcurrentHashMap、Hashtable、ArrayBlockingQueue等集合保证多线程环境下的原子性
- AtomicBoolean、AtomicInteger、AtomicLong等
java.util.concurrent.atomic
相关类 - ReetrantLock和Condition一起使用,保证方法、语句块的原子性
- ThreadLocal声明为static匿名内部类保证某个变量的原子性
Java原子操作类汇总
https://www.cnblogs.com/senlinyang/p/7856339.html
问题七
文件或目录 | 作用 |
---|---|
META-INF/ |
存放签名信息,保证apk的完整性和系统安全 |
lib/ |
如果存在的话,存放的是NDK编译出来的so文件 |
res/ |
存放资源文件 |
resources.arsc |
存放编译后的二进制资源文件 |
classes.dex |
将.class文件转换成的dalvik字节码 |
AndroidManifest.xml |
存放程序全局配置信息 |
Android中apk文件的结构解析
https://blog.csdn.net/zengrun1992/article/details/40076767
问题八
现阶段本人主要通过看书、写总结、逛开源社区的方式提供自己的技术,弥补自身的短板,阅读的书籍包括:重构-改善既有代码的设计、Head First Design Pattern、Head First Java 2nd Edition、Android开发艺术探索、Android自定义组件开发详解、Android性能优化最佳实践等,正在读的书籍有:图解HTTP、Kotlin实战、Java并发编程实战等,之后自己会往自定义组件这个方向去发展,包括:View的绘制、View动画、View手势处理、View内存优化等
问题九
- await、signal和signalAll来自Condition提供的方法,用来阻塞线程和唤醒线程
- wait、notify和notifyAll来自Object提供的方法,用来阻塞线程和唤醒线程
- 一个Lock可以获得多个Condition,允许多个队列在等待,在多个线程等待中,Condition可以唤醒特定的线程
- Object发送广播通知,满足条件的线程被唤醒,无法指定唤醒哪个线程
问题十
使用Set
集合的唯一性,可以快速去掉一个集合中重复的元素。
问题十一
HashMap容量不足时进行resize由于高并发可能出现死链,导致CPU飙升,在开发中可以考虑使用其他数据结构代替或加锁来避免此风险
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/2728.html ,谢谢支持!