端点科技后端面经

1. python和java的区别
从大的方面说:
1、python 既面向对象又面向函数;java存面向对象
2、python 简单,开发效率高,但运行效率慢;java运行效率相对高。
3、python 比java更方便的调用c或c++的库。
4、python 拥有大量的计算第三方库,更适合科学计算,数据分析等研究工作,而java 更适合商业开发。
5、python 有全局解析性锁,Java支持真正的多线程并发操作,能很好的控制资源的的共享。
6、python是动态语言,而java是静态语言。
从细节上说:
1、java 单继承,而python 多继承。
2、python只有四种数据:整数,长整数、浮点数和复数 java则有char,short,byte,int,long,float,double类型。
3、语法上的一些区别
解析:java为啥不支持多继承,多继承会出现歧义。
python 有个方法顺序解析列表,而且支持函数传参不确定操作。
2. hashmap和hashtable的区别
a. 线程是否安全:Hashmap不是线程安全的,hashtable是线程安全的,因为hashtable内部的方法基本都被synchronized修饰。(可以使用currenthashmap保证线程安全)。
b. 效率:因为线程安全问题,hashmap执行效率比hashtable效率高。(hashtable现在基本已经被淘汰,最好不要使用)。
c. 对null key 和 null value的支持:hashmap可以存储null的key和value,但null作为key只能有一个,null作为value可以有多个。Hashtable不允许有null的key和value。
d. 初始容量大小和每次扩容大小:(1)创建时不指定初始大小:hashtable的默认大小为11,每次扩容之后容量变为原来的2n+1,hashmap的初始容量大小为16,每次扩容之后变为原来的2倍。(2)创建时指定初始大小:hashtable会直接使用给定的大小,而hahsmap会将其扩容为2的幂次方。
3. hashtable底层数据结构以及怎么实现线程安全的
HashTable类中,保存实际数据的,依然是Entry对象,其数据结构是数组加链表。HashTable类继承自Dictionary类,实现了三个接口,分别是Map,Cloneable和java.io.Serializable。
4. hashmap的底层数据结构
jdk1.7中与hashtable相同,为数组加链表。
jdk1.8之后引入了红黑树,在解决哈希冲突时有了较大变化,当链表长度大于阈值(默认为8),(在转化为红黑树之前会判断数组的长度,如果小于64,会先对数组进行扩容)将链表转化为红黑树,以减少搜索时间。
5. 红黑树查询效率为什么比较高
红黑树属于弱平衡二叉树。它不严格是因为它不是严格控制左、右子树高度或节点数之差小于等于1,但红黑树高度依然是平均log(n),且最坏情况高度不会超过2log(n)。红黑树能够以O(log2(N))的时间复杂度进行搜索、插入、删除操作。此外,任何不平衡都会在3次旋转之内解决。
6. currenthashmap怎么保证线程安全的
在JDK1.7中ConcurrentHashMap采用了数组+Segment+分段锁的方式实现。在数组基础上增加了一层Segment,一个Segment对应数组的一段,这样对某段进行的操作只需要锁住对应段,不影响其他段的操作。其中,Segment继承了ReentrantLock并实现了序列化接口,说明Segment的锁是可重入的。
在jdk1.8中取消了Segment分段锁的数据结构,取而代之的是Node,Node的value和next都是由volatile关键字进行修饰,可以保证可见性。将细化的粒度从段进一步降低到节点。线程安全实现上,采用CAS+Synchronized替代Segment分段锁。
7. jvm模型
JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
程序计数器(线程私有):是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器,这类内存也称为“线程私有”的内存。正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果是Natice方法,则为空。
java 虚拟机栈(线程私有):每个方法在执行的时候也会创建一个栈帧,存储了局部变量,操作数,动态链接,方法返回地址。每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。通常所说的栈,一般是指在虚拟机栈中的局部变量部分。局部变量所需内存在编译期间完成分配,如果线程请求的栈深度大于虚拟机所允许的深度,则StackOverflowError。如果虚拟机栈可以动态扩展,扩展到无法申请足够的内存,则OutOfMemoryError。
本地方法栈(线程私有):和虚拟机栈类似,主要为虚拟机使用到的Native方法服务。也会抛出StackOverflowError 和OutOfMemoryError。
**Java堆(线程共享):**被所有线程共享的一块内存区域,在虚拟机启动的时候创建,用于存放对象实例。对可以按照可扩展来实现(通过-Xmx 和-Xms 来控制)当队中没有内存可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
方法区(线程共享):被所有方法线程共享的一块内存区域。用于存储已经被虚拟机加载的类信息,常量,静态变量等。这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。
8. gc算法
复制算法:
将内存分为两块,当一块内存用完了,就将存活的对象复制到另一块内存中。
优点:空间连续,没有内存碎片,运行效率高。
缺点:占用内存,如果复制长期生存的对象,会导致效率低。
主要用在新生代,因为新生代对象存活率低。
标记-清除算法:
先标记出需要清除的对象,再将标记的对象回收。
优点:占用内存小
缺点:
(1)需要进行两次动作,标记和清除,所以效率低。
(2)回收完之后,内存不连续,会有内存碎片。
标记-整理算法:
先标记出需要清除的对象,但是不进行回收,而是让所有存活对象都向一段移动,然后清除边界之外的内存空间。
优点:占用内存小,没有内存碎片
缺点:效率低
分代收集算法:
根据Java堆的新生代和老年代的特点,选用不同的回收算法。新生代内存空间大,对象会大量死去,回收频繁,使用效率高的复制算法,只需要每次复制少量存活下来的对象即可。老年代内存空间小,对象存活率高,使用标记-清除/标记-整理算法。
9. JVM如何判断哪些对象可以被回收
引用计数器算法:
引用计数器的算法原理:给对象添加一个引用计数器,每当有一个地方引用它时,计数器的值就会加1;当引用失效时,计数器就会减1;在任何时刻计数器的值为0的对象就是不可能再被使用的,也就是被回收的对象。
引用计数器算法效率高,但是主流的JVM并没有选用这种算法来判断可回收对象,因为它有一个致命的缺陷,就是无法解决对象之间循环引用的问题,对于循环引用的对象,无法进行回收。
可达性分析算法:
在主流的JVM实现中,都是通过可达性分析算法来判断对象时候存活的。其基本思想:通过一系列被称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots对象没有任何引用链相连,就认为GC Roots到这个对象是不可达的,判定为不可用对象,可以被回收。
10. 线程和进程的区别
线程定义:线程是进程的基本执行单元,一个进程的所有任务都在线程中执行,进程要想执行任务,必须得有线程,进程至少要有一条线程,程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程
进程定义:进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存
进程与线程的区别:线程是进程划分的更小的基本单位,一个进程在其执行过程中可以产生多个线程。线程和进程最大的区别在于基本上各个进程是相互独立的,而同一个进程的线程则可能会相互影响,因为他们会共享堆,和方法区。线程的开销小,但不利于资源的管理和保护,而进程相反。
11. Wait、notify、notify all
wait():使当前线程进入到阻塞状态直到其他线程通过 notify()/notifyAll()来唤醒。
wait(long timeout):在wait()的基础上,设置了一个超时时间,超过这个时间会自主唤醒。
notify():唤醒在此同步锁对象上等待的单个线程。如果有多个线程都在此同步锁对象上等待,则会任意选择其中某个线程进行唤醒操作,只有当前线程放弃对同步锁对象的锁定,才有可能执行被唤醒的线程。
notifyAll():和notify()的区别为唤醒同步锁对象上等待的所有线程。
12. Threadlocal
hreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。
13. 内存泄漏和内存溢出
内存泄漏memory leak :是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
内存溢出 out of memory :指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。
14. Threadlocal内存泄漏问题
ThreadlocalMap中使用的key为Threadlocal的弱引用,而value是强引用。所以,如果,Threadlocal在没有被外部强引用的情况下,在垃圾回收的时候,key会被清理掉,而value不会被清理掉,这样, ThreadMap中就会出现key为null的entry,如果不作任何措施,value永远不会被GC回收,这时候就可能产生内存泄漏。ThreadLocalMap的实现中已经考虑了这个问题,在调用set(),get(),remove()方法的时候,会清理掉key为null的记录。
15. Redis为什么被广泛使用
数据存储在内存速度快
支持数据持久化(AOF和RDB两种持久化方式)
Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合。
支持事务
支持主从复制
支持高可用、分布式
16. Redis持久化的两种方式及实现细节
RDB机制:RDB其实就是把数据以快照的形式保存在磁盘上。指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
RDB 的优势和劣势
① 、优势
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
②、劣势
RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
**AOF机制:**全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
优点
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据
缺点
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。
17. Redis单线程
单进程单线程优势:代码更清晰,处理逻辑更简单。不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。不存在多进程或者多线程导致的切换而消耗CPU
单进程单线程弊端:无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善。
IO多路复用技术:redis 采用网络IO多路复用技术来保证在多连接的时候, 系统的高吞吐量。
18. Redis为什么这么快?
完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。
数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的。
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
使用多路 I/O 复用模型,非阻塞 IO;
使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值