lock()获得锁 unlock()释放锁
4)使用局部变量 ThreadLocal 实现线程同步,每个线程都会保存一份该变量的 副本,副本之间相互独立,这样每个线程都可以随意修改自己的副本,而不影响 其他线程。常用方法 ThreadLocal()创建一个线程本地变量;get()返回此线程局 部的当前线程副本变量;initialValue()返回此线程局部变量的当前线程的初始 值;set(T value)将此线程变量的当前线程副本中的值设置为 value
5)使用原子变量,如 AtomicInteger,常用方法 AtomicInteger(int value)创 建个有给定初始值的 AtomicInteger 整数;addAndGet(int data)以原子方式 将给定值与当前值相加
6)使用阻塞队列实现线程同步 LinkedBlockingQueue
9、如何保证线程安全? 线程安全性体现在三方法:
1)原子性:提供互斥访问,同一时刻只能有一个线和至数据进行操作。 JDK 中 提 供 了 很 多 atomic 类 , 如 AtomicInteger\AtomicBoolean\AtomicLong,它们是通过 CAS 完成原子性。 JDK 提供锁分为两种:synchronized 依赖 JVM 实现锁,该关键字作用对象的 作用范围内同一时刻只能有一个线程进行操作。另一种是 LOCK,是 JDK 提供的
代码层面的锁,依赖 CPU 指令,代表性是 ReentrantLock。
2)可见性:一个线程对主内存的修改及时被其他线程看到。
JVM 提供了 synchronized 和 volatile,volatile 的可见性是通过内存屏障和禁 止重排序实现的,volatile 会在写操作时,在写操作后加一条 store 屏障指令, 将本地内存中的共享变量值刷新到主内存;会在读操作时,在读操作前加一条 load 指令,从内存中读取共享变量。
3)有序性:指令没有被编译器重排序。
可通过 volatile、synchronized、Lock 保证有序性。
10、两个进程同时要求写或者读,能不能实现?如何防止进程的同步?
我认为可以实现,比如两个进程都读取日历进程数据是没有问题,但同时写,应 该会有冲突。
可以使用共享内存实现进程间数据共享。
11、线程间操作 List
12、Java 中对象的生命周期
1)创建阶段(Created):为对象分配存储空间,开始构造对象,从超类到子 类对 static 成员初始化;超类成员变量按顺序初始化,递归调用超类的构造方法, 子类成员变量按顺序初始化,子类构造方法调用。
2)应用阶段(In Use):对象至少被一个强引用持有着。
3)不可见阶段(Invisible):程序运行已超出对象作用域
4)不可达阶段(Unreachable):该对象不再被强引用所持有
5)收集阶段(Collected):假设该对象重写了 finalize()方法且未执行过,会 去执行该方法。
6)终结阶段(Finalized):对象运行完 finalize()方法仍处于不可达状态,等待 垃圾回收器对该对象空间进行回收。
7)对象空间重新分配阶段(De-allocated):垃圾回收器对该对象所占用的内 存空间进行回收或再分配,该对象彻底消失。
13、static synchronized 方法的多线程访问和作用
static synchronized 控制的是类的所有实例访问,不管 new 了多少对象,只有一份,所以对该类的所有对象都加了锁。限制多线程中该类的所有实例同时访问 JVM 中该类对应的代码。
14、同一个类里面两个 synchronized 方法,两个线程同时访问的问题
如果 synchronized 修饰的是静态方法,锁的是当前类的 class 对象,进入同步 代码前要获得当前类对象的锁;
普通方法,锁的是当前实例对象,进入同步代码前要获得的是当前实例的锁;
同步代码块,锁的是括号里面的对象,对给定的对象加锁,进入同步代码块库前 要获得给定对象锁;
如果两个线程访问同一个对象的 synchronized 方法,会出现竞争,如果是不同 对象,则不会相互影响。
15、volatile 的原理
有volatile变量修饰的共享变量进行写操作的时候会多一条汇编代码,lock addl $0x0,lock 前缀的指令在多核处理器下会将当前处理器缓存行的数据会写回到 系统内存,这个写回内存的操作会引起在其他 CPU 里缓存了该内存地址的数据 无效。同时 lock 前缀也相当于一个内存屏障,对内存操作顺序进行了限制。
16、synchronized 原理
synchronized 通过对象的对象头(markword)来实现锁机制,java 每个对象都 有对象头,都可以为 synchronized 实现提供基础,都可以作为锁对象,在字节 码层面 synchronized 块是通过插入 monitorenter monitorexit 完成同步的。 持有 monitor 对象,通过进入、退出这个 Monitor 对象来实现锁机制。
17、谈谈 NIO 的理解
NIO( New Input/ Output) 引入了一种基于通道和缓冲区的 I/O 方式,它可以 使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆的 DirectByteBuffer 对象作为这块内存的引用进行操作,避免了在 Java 堆和 Native 堆中来回复制数据。 NIO 是一种同步非阻塞的 IO 模型。同步是指线 程不断轮询 IO 事件是否就绪,非阻塞是指线程在等待 IO 的时候,可以同时 做其他任务。同步的核心就是 Selector,Selector 代替了线程本身轮询 IO 事 件,避免了阻塞同时减少了不必要的线程消耗;非阻塞的核心就是通道和缓冲区, 当 IO 事件就绪时,可以通过写道缓冲区,保证 IO 的成功,而无需线程阻塞 式地等待。
-synchronized 和 volatile 关键字的区别
-synchronized 与 Lock 的区别
-ReentrantLock 、synchronized 和 volatile 比较
1)volatile:解决变量在多个线程间的可见性,但不能保证原子性,只能用于修 饰变量,不会发生阻塞。volatile 能屏蔽编译指令重排,不会把其后面的指令排 到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面。多用于并行
计算的单例模式。volatile 规定 CPU 每次都必须从内存读取数据,不能从 CPU 缓存中读取,保证了多线程在多 CPU 计算中永远拿到的都是最新的值。
2)synchronized:互斥锁,操作互斥,并发线程过来,串行获得锁,串行执行 代码。解决的是多个线程间访问共享资源的同步性,可保证原子性,也可间接保 证可见性,因为它会将私有内存和公有内存中的数据做同步。可用来修饰方法、 代码块。会出现阻塞。synchronized 发生异常时,会自动释放线程占有的锁, 因此不会导致死锁现象发生。非公平锁,每次都是相互争抢资源。
3)lock 是一个接口,而 synchronized 是 java 中的关键字,synchronized 是 内置语言的实现。lock 可以让等待锁的线程响应中断。在发生异常时,如果没 有主动通过 unLock()去释放锁,则可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。
4)ReentrantLock 可重入锁,锁的分配机制是基于线程的分配,而不是基于方 法调用的分配。ReentrantLock 有 tryLock 方法,如果锁被其他线程持有,返 回 false,可避免形成死锁。对代码加锁的颗粒会更小,更节省资源,提高代码 性能。ReentrantLock 可实现公平锁和非公平锁,公平锁就是先来的先获取资 源。ReentrantReadWriteLock 用于读多写少的场合,且读不需要互斥场景。 -ReentrantLock 的内部实现 -lock 原理
- 死锁的四个必要条件?
- 怎么避免死锁?
- 对象锁和类锁是否会互相影响?
- 什么是线程池,如何使用?
- Java 的并发、多线程、线程模型
- 谈谈对多线程的理解 -多线程有什么要注意的问题?
- 谈谈你对并发编程的理解并举例说明
- 谈谈你对多线程同步机制的理解?
- 如何保证多线程读写文件的安全?
- 多线程断点续传原理 -断点续传的实现
5)并发编程有关知识点(这个是一般 Android 开发用的少的,所以建议多 去看看):
平时 Android 开发中对并发编程可以做得比较少,Thread 这个类经常会用到, 但是我们想提升自己的话,一定不能停留在表面,,我们也应该去了解一下 java 的关于线程相关的源码级别的东西。
1、图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处
理?
-
参考回答:
-
首先我们要清楚图片的三级缓存是如何的
如果内存足够时不回收。内存不够时就回收软引用对象
2、内存中如果加载一张 500*500 的 png 高清图片.应该是占用多少的内存?
-
参考回答:
-
不考虑屏幕比的话:占用内存=500 * 500 * 4 = 1000000B ≈ 0.95MB
-
考虑屏幕比的的话:占用内存= 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x(inTargetDensity / inDensity)x 一个像素所占的内存字节大小
-
inDensity 表示目标图片的 dpi(放在哪个资源文件夹下),inTargetDensity 表示目标屏幕的 dpi
3、WebView 的性能优化 ?
-
参考回答:
-
一个加载网页的过程中,native、网络、后端处理、CPU 都会参与,各自都有必要的工作和依赖关系;让他们相互并行处理
而不是相互阻塞才可以让网页加载更快:
-
WebView 初始化慢,可以在初始化同时先请求数据,让后端和网络不要闲着。
-
常用 JS 本地化及延迟加载,使用第三方浏览内核
-
后端处理慢,可以让服务器分 trunk 输出,在后端计算的同时前端也加载网络静态资源。
-
脚本执行慢,就让脚本在最后运行,不阻塞页面解析。
-
同时,合理的预加载、预缓存可以让加载速度的瓶颈更小。
-
WebView 初始化慢,就随时初始化好一个 WebView待用。
-
DNS 和链接慢,想办法复用客户端使用的域名和链接。
4、Bitmap 如何处理大图,如一张 30M 的大图,如何预防 OOM?
-
参考回答:避免 OOM 的问题就需要对大图片的加载进行管理,主要通过缩放来减小图片的内存占用。
-
BitmapFactory 提供的加载图片的四类方法(decodeFile、decodeResource、decodeStream、decodeByteArray)
都支持 BitmapFactory.Options 参数,通过 inSampleSize 参数就可以很方便地对一个图片进行采样缩放
- 比如一张 10241024 的高清图片来说。那么它占有的内存为102410244,即 4MB,如果 inSampleSize 为 2,那么采样后
的图片占用内存只有 512512*4,即 1MB(**注意:根据最新的官方文档指出,inSampleSize 的取值应该总是为 2 的指数,即
1、2、4、8 等等,如果外界输入不足为 2 的指数,系统也会默认选择最接近 2 的指数代替,比如 2**)
-
综合考虑。通过采样率即可有效加载图片,流程如下
-
将 BitmapFactory.Options 的 inJustDecodeBounds 参数设为 true 并加载图片
-
从 BitmapFactory.Options 中取出图片的原始宽高信息,它们对应 outWidth 和 outHeight 参数
-
根据采样率的规则并结合目标 View 的所需大小计算出采样率 inSampleSize
-
将 BitmapFactory.Options 的inJustDecodeBounds 参数设为 false,重新加载图片
5、内存回收机制与 GC 算法(各种算法的优缺点以及应用场景);GC 原理时机
以及 GC 对象
-
参考回答:
-
内存判定对象可回收有两种机制:
-
引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加 1;当引用失效时,计数器值就减 1;任何时刻计数器为 0 的对象就是不可能再被使用的。然而在主流的 Java 虚拟机里未选用引用计数算法来管理内存,主要原因是它难以解决对象之间相互循环引用的问题,所以出现了另一种对象存活判定算法。
-
可达性分析法:通过一系列被称为『GCRoots』的对象作为起始点,从这些节点开始向下搜索,搜索所走过的
路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。其中可作为 GC Roots 的对象:虚拟机栈中引用的对象,主要是指栈帧中的本地变量*、本地方法栈中 Native 方法引用的对
象、方法区中类静态属性引用的对象、方法区中常量引用的对象
-
GC 回收算法有以下四种:
-
分代收集算法:是当前商业虚拟机都采用的一种算法,根据对象存活周期的不同,将 Java 堆划分为新生代和老
年代,并根据各个年代的特点采用最适当的收集算法。
-
新生代:大批对象死去,只有少量存活。使用『复制算法』,只需复制少量存活对象即可。
-
复制算法:把可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用尽后,把还存活着的对象『复制』到另外一块上面,再将这一块内存空间一次清理掉。**实现简单,运行高效。在对象存活率较高时就要进行较
多的复制操作,效率将会变低**
-
老年代:对象存活率高。使用『标记—清理算法』或者『标记—整理算法』,只需标记较少的回收对象即可。
-
标记-清除算法:首先『标记』出所有需要回收的对象,然后统一『清除』所有被标记的对象。标记和清除两个过程的效率都不高,清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
-
标记-整理算法:首先『标记』出所有需要回收的对象,然后进行『整理』,使得存活的对象都向一端移动,最后直接清理掉端边界以外的内存。标记整理算法会将所有的存活对象移动到一端,并对不存活对象进行处理,因此其不会产生内存碎片
6、内存泄露和内存溢出的区别 ?AS 有什么工具可以检测内存泄露
-
参考回答:
-
内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory;比如申请了一
个 integer,但给它存了 long 才能存下的数,那就是内存溢出。
-
内存泄露(memory leak):是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致 out of memory!
-
查找内存泄漏可以使用 Android Studio 自带的AndroidProfiler工具或 MAT
7、性能优化,怎么保证应用启动不卡顿? 黑白屏怎么处理?
-
参考回答:
-
应用启动速度,取决于你在 application 里面时候做了什么事情,比如你集成了很多 sdk,并且 sdk 的 init 操作都需要在主
线程里实现所以会有卡顿的感觉。在非必要的情况下可以把加载延后或则开启子线程处理
-
另外,影响界面卡顿的两大因素,分别是界面绘制和数据处理。
-
布局优化(使用 include,merge 标签,复杂布局推荐使用 ConstraintLayout 等)
-
onCreate() 中不执行耗时操作 把页面显示的 View 细分一下,放在 AsyncTask 里逐步显示,用 Handler更好。这样用户的看到的就是有层次有步骤的一个个的View 的展示,不会是先看到一个黑屏,然后一下显示所有 View。最好做成动画,效果更自然。s
-
利用多线程的目的就是尽可能的减少 onCreate() 和onReume() 的时间,使得用户能尽快看到页面,操作页面。
-
减少主线程阻塞时间。
-
提高 Adapter 和 AdapterView 的效率。
-
黑白屏产生原因:当我们在启动一个应用时,系统会去检查是否已经存在这样一个进程,如果不存在,系统的服务会先检查startActivity 中的 intent 的信息,然后在去创建进程,最后启动 Acitivy,即冷启动。而启动出现白黑屏的问题,就是在这段
时间内产生的。系统在绘制页面加载布局之前,首先会初始化窗口(Window),而在进行这一步操作时,系统会根据我们设
置的 Theme 来指定它的 Theme 主题颜色,我们在 Style 中的设置就决定了显示的是白屏还是黑屏。
-
windowIsTranslucent 和 windowNoTitle,将这两个属性都设置成 true (会有明显的卡顿体验,不推荐)
-
如果启动页只是是一张图片,那么为启动页专一设置一个新的主题,设置主题的android:windowBackground 属性为启动页背景图即可
-
使用 layer-list 制作一张图片 launcher_layer.xml,将其设置为启动页专一主题的背景,并将其设置为启动页布局的背景。
8、强引用置为 null,会不会被回收?
-
参考回答:
-
不会立即释放对象占用的内存。 如果对象的引用被置为 null,只是断开了当前线程栈帧中对该对象的引用关系,而 垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点(safepoint)或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize 方法中恢复引用 )。只有确定了对象无法恢复引用的时候才会清除对象内存。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
Android 基础知识点
Java 基础知识点
Android 源码相关分析
常见的一些原理性问题
希望大家在今年一切顺利,进到自己想进的公司,共勉!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
Android 基础知识点
Java 基础知识点
Android 源码相关分析
常见的一些原理性问题
[外链图片转存中…(img-isJA8b6h-1712914241797)]
希望大家在今年一切顺利,进到自己想进的公司,共勉!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-doH5Hc1I-1712914241798)]