网站建设后台有哪些东西,wordpress自定义栏目上传图片,网站建设 软文发布,2023能用的磁力搜索引擎关于面试字节跳动#xff0c;我总结一些面试点#xff0c;希望可以帮到更多的小伙伴#xff0c;由于篇幅问题这里没有把全部的面试知识点问题都放上来#xff01;#xff01;目录#xff1a;1.网络2.Java 基础容器同步设计模式3.Java 虚拟机内存结构…关于面试字节跳动我总结一些面试点希望可以帮到更多的小伙伴由于篇幅问题这里没有把全部的面试知识点问题都放上来目录1.网络2.Java 基础容器同步设计模式3.Java 虚拟机内存结构GC类加载四种引用动态代理4.Android 基础性能优化Framwork5.音视频FFmpeg播放器1、网络网络协议模型应用层负责处理特定的应用程序细节HTTP、FTP、DNS传输层为两台主机提供端到端的基础通信TCP、UDP网络层控制分组传输、路由选择等IP链路层操作系统设备驱动程序、网卡相关接口TCP 和 UDP 区别TCP 连接可靠有序面向字节流速度慢较重量全双工适用于文件传输、浏览器等全双工A 给 B 发消息的同时B 也能给 A 发半双工A 给 B 发消息的同时B 不能给 A 发UDP 无连接不可靠无序面向报文速度快轻量适用于即时通讯、视频通话等TCP 三次握手A你能听到吗B我能听到你能听到吗A我能听到开始吧A 和 B 两方都要能确保我说的话你能听到你说的话我能听到。所以需要三次握手TCP 四次挥手A我说完了B我知道了等一下我可能还没说完B我也说完了A我知道了结束吧B 收到 A 结束的消息后 B 可能还没说完没法立即回复结束标示只能等说完后再告诉 A 我说完了。POST 和 GET 区别Get 参数放在 url 中Post 参数放在 request Body 中Get 可能不安全因为参数放在 url 中HTTPSHTTP 是超文本传输协议明文传输HTTPS 使用 SSL 协议对 HTTP 传输数据进行了加密HTTP 默认 80 端口HTTPS 默认 443 端口优点安全缺点费时、SSL 证书收费加密能力还是有限的但是比 HTTP 强多了2、Java 基础容器同步设计模式StringBuilder、StringBuffer、、String.concat 链接字符串StringBuffer 线程安全StringBuilder 线程不安全实际上是用 StringBuilder 来实现的所以非循环体可以直接用 循环体不行因为会频繁创建 StringBuilderString.concat 实质是 new String 效率也低耗时排序StringBuilder StringBuffer concat Java 泛型擦除修饰成员变量等类结构相关的泛型不会被擦除容器类泛型会被擦除ArrayList、LinkedListArrayList基于数组实现查找快o(1)增删慢o(n)初始容量为10扩容通过 System.arrayCopy 方法LinkedList基于双向链表实现查找慢o(n)增删快o(1)封装了队列和栈的调用HashMap 、HashTableHashMap基于数组和链表实现数组是 HashMap 的主体链表是为解决哈希冲突而存在的当发生哈希冲突且链表 size 大于阈值时会扩容JAVA 8 会将链表转为红黑树提高性能允许 key/value 为 nullHashTable数据结构和 HashMap 一样不允许 value 为 null线程安全ArrayMap、SparseArrayArrayMap1.基于两个数组实现一个存放 hash一个存放键值对。扩容的时候只需要数组拷贝不需要重建哈希表2.内存利用率高3.不适合存大量数据因为会对 key 进行二分法查找1000以下SparseArray1.基于两个数组实现int 做 key2.内存利用率高3.不适合存大量数据因为会对 key 进行二分法查找1000以下volatile 关键字只能用来修饰变量适用修饰可能被多线程同时访问的变量相当于轻量级的 synchronizedvolatitle 能保证有序性禁用指令重排序、可见性后者还能保证原子性变量位于主内存中每个线程还有自己的工作内存变量在自己线程的工作内存中有份拷贝线程直接操作的是这个拷贝被 volatile 修饰的变量改变后会立即同步到主内存保持变量的可见性。双重检查单例为什么要加 volatile1.volatile想要解决的问题是在另一个线程中想要使用instance发现instance!null但是实际上instance还未初始化完毕这个问题2.将instance newInstance();拆分为3句话是。1.分配内存2.初始化3.将instance指向分配的内存空3.volatile可以禁止指令重排序确保先执行2后执行3wait 和 sleepsleep 是 Thread 的静态方法可以在任何地方调用wait 是 Object 的成员方法只能在 synchronized 代码块中调用否则会报 IllegalMonitorStateException 非法监控状态异常sleep 不会释放共享资源锁wait 会释放共享资源锁lock 和 synchronizedsynchronized 是 Java 关键字内置特性Lock 是一个接口synchronized 会自动释放锁lock 需要手动释放所以需要写到 try catch 块中并在 finally 中释放锁synchronized 无法中断等待锁lock 可以中断Lock 可以提高多个线程进行读/写操作的效率竞争资源激烈时lock 的性能会明显的优于 synchronized3、Java 虚拟机内存结构GC类加载四种引用动态代理JVM定义可以理解成一个虚构的计算机解释自己的字节码指令集映射到本地 CPU 或 OS 的指令集上层只需关注 Class 文件与操作系统无关实现跨平台Kotlin 就是能解释成 Class 文件所以可以跑在 JVM 上JVM 内存模型Java 多线程之间是通过共享内存来通信的每个线程都有自己的本地内存共享变量存放于主内存中线程会拷贝一份共享变量到本地内存volatile 关键字就是给内存模型服务的用来保证内存可见性和顺序性JVM 内存结构线程私有1.程序计数器记录正在执行的字节码指令地址若正在执行 Native 方法则为空2.虚拟机栈执行方法时把方法所需数据存为一个栈帧入栈执行完后出栈3.本地方法栈同虚拟机栈但是针对的是 Native 方法线程共享1.堆存储 Java 实例GC 主要区域分代收集 GC 方法会吧堆划分为新生代、老年代2.方法区存储类信息常量池静态变量等数据GC回收区域只针对堆、方法区线程私有区域数据会随线程结束销毁不用回收回收类型1.堆中的对象分代收集 GC 方法会吧堆划分为新生代、老年代新生代新建小对象会进入新生代通过复制算法回收对象老年代新建大对象及老对象会进入老年代通过标记-清除算法回收对象2.方法区中的类信息、常量池判断一个对象是否可被回收1.引用计数法缺点循环引用2.可达性分析法定义从 GC ROOT 开始搜索不可达的对象都是可以被回收的GC ROOT1.虚拟机栈/本地方法栈中引用的对象2.方法区中常量/静态变量引用的对象四种引用强引用不会被回收软引用内存不足时会被回收弱引用gc 时会被回收虚引用无法通过虚引用得到对象可以监听对象的回收ClassLoader类的生命周期1.加载2.验证3.准备4.解析5.初始化6.使用7.卸载类加载过程1.加载获取类的二进制字节流生成方法区的运行时存储结构在内存中生成 Class 对象2.验证确保该 Class 字节流符合虚拟机要求3.准备初始化静态变量4.解析将常量池的符号引用替换为直接引用5.初始化执行静态块代码、类变量赋值类加载时机1.实例化对象2.调用类的静态方法3.调用类的静态变量放入常量池的常量除外类加载器负责加载 class 文件分类1.引导类加载器 - 没有父类加载器2.拓展类加载器 - 继承自引导类加载器3.系统类加载器 - 继承自拓展类加载器双亲委托模型当要加载一个 class 时会先逐层向上让父加载器先加载加载失败才会自己加载为什么叫双亲不考虑自定义加载器系统类加载器需要网上询问两层所以叫双亲判断是否是同一个类时除了类信息还必须时同一个类加载器优点防止重复加载父加载器加载过了就没必要加载了安全防止篡改核心库类动态代理原理及实现InvocationHandler 接口动态代理类需要实现这个接口Proxy.newProxyInstance用于动态创建代理对象Retrofit 应用 Retrofit 通过动态代理为我们定义的请求接口都生成一个动态代理对象实现请求4、Android 基础性能优化FramworkActivity 启动模式standard 标准模式singleTop 栈顶复用模式推送点击消息界面singleTask 栈内复用模式首页singleInstance 单例模式单独位于一个任务栈中拨打电话界面细节taskAffinity任务相关性用于指定任务栈名称默认为应用包名allowTaskReparenting允许转移任务栈View 工作原理DecorView (FrameLayout)LinearLayouttitlebarContent调用 setContentView 设置的 ViewViewRoot 的 performTraversals 方法调用触发开始 View 的绘制然后会依次调用:performMeasure遍历 View 的 measure 测量尺寸performLayout遍历 View 的 layout 确定位置performDraw遍历 View 的 draw 绘制事件分发机制一个 MotionEvent 产生后按 Activity - Window - decorView - View 顺序传递View 传递过程就是事件分发主要依赖三个方法:dispatchTouchEvent用于分发事件只要接受到点击事件就会被调用返回结果表示是否消耗了当前事件onInterceptTouchEvent用于判断是否拦截事件当 ViewGroup 确定要拦截事件后该事件序列都不会再触发调用此 ViewGroup 的 onInterceptonTouchEvent用于处理事件返回结果表示是否处理了当前事件未处理则传递给父容器处理细节一个事件序列只能被一个 View 拦截且消耗View 没有 onIntercept 方法直接调用 onTouchEvent 处理OnTouchListener 优先级比 OnTouchEvent 高onClickListener 优先级最低requestDisallowInterceptTouchEvent 可以屏蔽父容器 onIntercet 方法的调用Window 、 WindowManager、WMS、SurfaceFlingerWindow抽象概念不是实际存在的而是以 View 的形式存在通过 PhoneWindow 实现WindowManager外界访问 Window 的入口内部与 WMS 交互是个 IPC 过程WMS管理窗口 Surface 的布局和次序作为系统级服务单独运行在一个进程SurfaceFlinger将 WMS 维护的窗口按一定次序混合后显示到屏幕上View 动画、帧动画及属性动画View 动画作用对象是 View可用 xml 定义建议 xml 实现比较易读支持四种效果平移、缩放、旋转、透明度帧动画通过 AnimationDrawable 实现容易 OOM属性动画可作用于任何对象可用 xml 定义Android 3 引入建议代码实现比较灵活包括 ObjectAnimator、ValuetAnimator、AnimatorSet时间插值器根据时间流逝的百分比计算当前属性改变的百分比系统预置匀速、加速、减速等插值器类型估值器根据当前属性改变的百分比计算改变后的属性值系统预置整型、浮点、色值等类型估值器使用注意事项避免使用帧动画容易OOM界面销毁时停止动画避免内存泄漏开启硬件加速提高动画流畅性 硬件加速将 cpu 一部分工作分担给 gpu 使用 gpu 完成绘制工作从工作分摊和绘制机制两个方面优化了绘制速度Handler、MessageQueue、LooperHandler开发直接接触的类内部持有 MessageQueue 和 LooperMessageQueue消息队列内部通过单链表存储消息Looper内部持有 MessageQueue循环查看是否有新消息有就处理没就阻塞如何实现阻塞通过 nativePollOnce 方法基于 Linux epoll 事件管理机制为什么主线程不会因为 Looper 阻塞系统每 16ms 会发送一个刷新 UI 消息唤醒MVC、MVP、MVVMMVPModel处理数据View控制视图Presenter分离 Activity 和 ModelMVVMModel处理获取保存数据View控制视图ViewModel数据容器使用 Jetpack 组件架构的 LiveData、ViewModel 便捷实现 MVVMSerializable、ParcelableSerializable Java 序列化方式适用于存储和网络传输serialVersionUID 用于确定反序列化和类版本是否一致不一致时反序列化回失败Parcelable Android 序列化方式适用于组件通信数据传递性能高因为不像 Serializable 一样有大量反射操作频繁 GCBinderAndroid 进程间通信的中流砥柱基于客户端-服务端通信方式使用 mmap 一次数据拷贝实现 IPC传统 IPC用户A空间-内核-用户B空间mmap 将内核与用户B空间映射实现直接从用户A空间-用户B空间BinderPool 可避免创建多 ServiceIPC 方式Intent extras、Bundle要求传递数据能被序列化实现 Parcelable、Serializable 适用于四大组件通信文件共享适用于交换简单的数据实时性不高的场景AIDLAIDL 接口实质上是系统提供给我们可以方便实现 BInder 的工具Android Interface Definition Language可实现跨进程调用方法服务端将暴漏给客户端的接口声明在 AIDL 文件中创建 Service 实现 AIDL 接口并监听客户端连接请求客户端绑定服务端 Service 绑定成功后拿到服务端 Binder 对象转为 AIDL 接口调用RemoteCallbackList 实现跨进程接口监听同个 Binder 对象做 key 存储客户端注册的 listener监听 Binder 断开1.Binder.linkToDeath 设置死亡代理2. onServiceDisconnected 回调Messenger基于 AIDL 实现服务端串行处理主要用于传递消息适用于低并发一对多通信ContentProvider基于 Binder 实现适用于一对多进程间数据共享SocketTCP、UDP适用于网络数据交换Android 系统启动流程按电源键 - 加载引导程序 BootLoader 到 RAM - 执行 BootLoader 程序启动内核 - 启动 init 进程 - 启动 Zygote 和各种守护进程 -启动 System Server 服务进程开启 AMS、WMS 等 - 启动 Launcher 应用进程5、音视频FFmpeg播放器FFmpeg基于命令方式实现了一个音视频编辑 Apphttps://github.com/yhaolpz/FFmpegCmd集成编译了 AAC、MP3、H264 编码器播放器原理视频播放原理mp4、flv- 解封装 - mp3/aac、h264/h265- 解码 - pcm、yuv- 音视频同步 - 渲染播放音视频同步选择参考时钟源音频时间戳、视频时间戳和外部时间三者选择一个作为参考时钟源一般选择音频因为人对音频更敏感ijk 默认也是音频通过等待或丢帧将视频流与参考时钟源对齐实现同步IjkPlayer 原理集成了 MediaPlayer、ExoPlayer 和 IjkPlayer 三种实现其中 IjkPlayer 基于 FFmpeg 的 ffplay音频输出方式AudioTrack、OpenSL ES视频输出方式NativeWindow、OpenGL ES关于算法算法Algorithm是指解题方案的准确而完整的描述是一系列解决问题的清晰指令算法代表着用系统的方法描述解决问题的策略机制。也就是说能够对一定规范的输入在有限时间内获得所要求的输出。如果一个算法有缺陷或不适合于某个问题执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。算法中的指令描述的是一个计算当其运行时能从一个初始状态和可能为空的初始输入开始经过一系列有限而清晰定义的状态最终产生输出并停止于一个终态。一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法包含了一些随机输入。算法一快速排序算法快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较但这种状况并不常见。事实上快速排序通常明显比其他Ο(n log n) 算法更快因为它的内部循环inner loop可以在大部分的架构上很有效率地被实现出来。快速排序使用分治法Divide and conquer策略来把一个串行list分为两个子串行sub-lists。算法步骤1 从数列中挑出一个元素称为 “基准”pivot2 重新排序数列所有元素比基准值小的摆放在基准前面所有元素比基准值大的摆在基准的后面相同的数可以到任一边。在这个分区退出之后该基准就处于数列的中间位置。这个称为分区partition操作。3 递归地recursive把小于基准值元素的子数列和大于基准值元素的子数列排序。递归的最底部情形是数列的大小是零或一也就是永远都已经被排序好了。虽然一直递归下去但是这个算法总会退出因为在每次的迭代iteration中它至少会把一个元素摆到它最后的位置去。算法二堆排序算法堆排序Heapsort是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构并同时满足堆积的性质即子结点的键值或索引总是小于或者大于它的父节点。堆排序的平均时间复杂度为Ο(nlogn) 。算法步骤创建一个堆H[0..n-1]把堆首最大值和堆尾互换3. 把堆的尺寸缩小1并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置4. 重复步骤2直到堆的尺寸为1算法三归并排序归并排序Merge sort台湾译作合并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法Divide and Conquer的一个非常典型的应用。算法步骤1. 申请空间使其大小为两个已经排序序列之和该空间用来存放合并后的序列2. 设定两个指针最初位置分别为两个已经排序序列的起始位置3. 比较两个指针所指向的元素选择相对小的元素放入到合并空间并移动指针到下一位置4. 重复步骤3直到某一指针达到序列尾5. 将另一序列剩下的所有元素直接复制到合并序列尾算法四二分查找算法二分查找算法是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始如果中间元素正好是要查找的元素则搜 素过程结束如果某一特定元素大于或者小于中间元素则在数组大于或小于中间元素的那一半中查找而且跟开始一样从中间元素开始比较。如果在某一步骤数组 为空则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。折半搜索每次把搜索区域减少一半时间复杂度为Ο(logn) 。算法五BFPRT(线性查找算法)BFPRT算法解决的问题十分经典即从某n个元素的序列中选出第k大第k小的元素通过巧妙的分 析BFPRT可以保证在最坏情况下仍为线性时间复杂度。该算法的思想与快速排序思想相似当然为使得算法在最坏情况下依然能达到o(n)的时间复杂 度五位算法作者做了精妙的处理。算法步骤1. 将n个元素每5个一组分成n/5(上界)组。2. 取出每一组的中位数任意排序方法比如插入排序。3. 递归的调用selection算法查找上一步中所有中位数的中位数设为x偶数个中位数的情况下设定为选取中间小的一个。4. 用x来分割数组设小于等于x的个数为k大于x的个数即为n-k。5. 若ik返回x若ik在小于x的元素中递归查找第i小的元素若ik在大于x的元素中递归查找第i-k小的元素。终止条件n1时返回的即是i小元素。算法六DFS深度优先搜索深度优先搜索算法Depth-First-Search是搜索算法的一种。它沿着树的深度遍历树的节点尽可能深的搜索树的分 支。当节点v的所有边都己被探寻过搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发 现的节点则选择其中一个作为源节点并重复以上过程整个进程反复进行直到所有节点都被访问为止。DFS属于盲目搜索。深度优先搜索是图论中的经典算法利用深度优先搜索算法可以产生目标图的相应拓扑排序表利用拓扑排序表可以方便的解决很多相关的图论问题如最大路径问题等等。一般用堆数据结构来辅助实现DFS算法。深度优先遍历图算法步骤1. 访问顶点v2. 依次从v的未被访问的邻接点出发对图进行深度优先遍历直至图中和v有路径相通的顶点都被访问3. 若此时图中尚有顶点未被访问则从一个未被访问的顶点出发重新进行深度优先遍历直到图中所有顶点均被访问过为止。上述描述可能比较抽象举个实例DFS 在访问图中某一起始顶点 v 后由 v 出发访问它的任一邻接顶点 w1再从 w1 出发访问与 w1邻 接但还没有访问过的顶点 w2然后再从 w2 出发进行类似的访问… 如此进行下去直至到达所有的邻接顶点都被访问过的顶点 u 为止。接着退回一步退到前一次刚访问过的顶点看是否还有其它没有被访问的邻接顶点。如果有则访问此顶点之后再从此顶点出发进行与前述类似的访问如果没有就再退回一步进行搜索。重复上述过程直到连通图中所有顶点都被访问过为止。算法七BFS(广度优先搜索)广度优先搜索算法Breadth-First-Search是一种图形搜索算法。简单的说BFS是从根节点开始沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问则算法中止。BFS同样属于盲目搜索。一般用队列数据结构来辅助实现BFS算法。算法步骤1. 首先将根节点放入队列中。2. 从队列中取出第一个节点并检验它是否为目标。如果找到目标则结束搜寻并回传结果。否则将它所有尚未检验过的直接子节点加入队列中。3. 若队列为空表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。4. 重复步骤2。6、最后面试题需要的更多关于Android面试题与答案的可以后台私信我【面试】我这边分享给你面试题答案点击这里备注CSDN