Java面试知识点总结(待更新)

7 篇文章 2 订阅

Java基础部分

集合框架

Java集合类主要由两个根接口CollectionMap派生出来的,Collection派生出了三个子接口:List、Set、Queue(Java5新增的队列),因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。

  • List代表了有序可重复集合,可直接根据元素的索引来访问;
  • Set代表无序不可重复集合,只能根据元素本身来访问;
  • Queue是队列集合;
  • Map代表的是存储key-value对的集合,可根据元素的key来访问value。
    集合体系中常用的实现类,分别是ArrayList、LinkedList、ArrayQueue、HashSet、TreeSet、HashMap、TreeMap等实现类。

每个实现类具体的知识点

补充:

  • 可以讲一下HashMap中的put方法的实现过程吗
    (这道题也就是间接问你关于hashmap的数据结构了)
           这得从它的底层数据结构说起,HashMap的是由数组+链表的结构实现的,阈值超过8,演化为红黑树它的内部封装了一个Entry数组,该数组也是一个哈希数组,故而存在哈希冲突的问题,HashMap是通过链地址法来解决冲突问题的,在每一个数组节点下封装一个单链表。
           所以put()方法添加一个新元素时先通过计算该元素的hash值,再通过hash&(length-1)确定该元素在Entry数组中的下标位置,若无元素则添加,若存在元素再通过equals方法来判断该元素是否在该链表中,如果不存在则放在头结点位置,如存在则不添加。

  • 当数组值达到峰值时,怎么进行扩展
           hashmap中有两个构造参数,一个初始容量(默认16),另一个为加载因子(默认0.75),当当前存储大于初始容量与加载因子的乘积值时,则进行扩容操作,每次已二倍的速率增长,最大值为2*30(幂次)。
           扩容是新建了一个数组,会重新计算hash来获取元素的新位置,所以扩容是一个相当耗时的操作。

多线程

可重入锁

强调对单个线程执行时重新进入同一个子程序仍然是安全的。

可中断锁

顾名思义,就是可以相应中断的锁。

公平锁

尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。

独享锁/共享锁

独享锁是指该锁一次只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。

互斥锁/读写锁

       上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。
       互斥锁在Java中的具体实现就是ReentrantLock
       读写锁在Java中的具体实现就是ReadWriteLock,读写锁将对一个资源(比如文件)的访问分成了2个锁,一个读锁和一个写锁。正因为有了读写锁,才使得多个线程之间的读操作不会发生冲突。

乐观锁/悲观锁

       乐观锁与悲观锁不是指具体的什么类型的锁,而是指看待并发同步的角度。
       悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。悲观锁在Java中的使用,就是利用各种锁。
       乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有事情的。
从上面的描述我们可以看出,悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。

分段锁

       分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。
       我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap(JDK7与JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。
       当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。
       但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。
       分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

偏向锁/轻量级锁/重量级锁

       这三种锁是指锁的状态,并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。
       偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
       轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
       重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。

自旋锁

       在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
       线程自旋和适应性自旋
       我们知道,java线程其实是映射在内核之上的,线程的挂起和恢复会极大的影响开销。
并且jdk官方人员发现,很多线程在等待锁的时候,在很短的一段时间就获得了锁,所以它们在线程等待的时候,并不需要把线程挂起,而是让他无目的的循环,一般设置10次。
       这样就避免了线程切换的开销,极大的提升了性能。
       而适应性自旋,是赋予了自旋一种学习能力,它并不固定自旋10次一下。他可以根据它前面线程的自旋情况,从而调整它的自旋,甚至是不经过自旋而直接挂起。

JavaWeb部分

HttpServletResponse

请求转发(302)和重定位(307)的区别

  • 相同点
    • 能够实现页面的跳转
  • 不同点
  1. 转发是一次请求,重定向是两次
  2. 转发不会改变url,重定向会改变
  3. 请求转发是在服务器内部完成的,而重定向是在客户端完成的
  4. 转发的url必须是当前web工程内部的地址,重定向可以是任意地址
  • 理解:重定向 = 甩锅的 转发 = 跑腿的
    在这里插入图片描述

Get和Post两种请求方法有什么区别

  • GET参数通过URL传递,POST放在Request body中。
  • GET产生一个TCP数据包;POST产生两个TCP数据包。
    • 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

    • 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200(返回数据)。

推荐内容

长安不及十里 - 2021最详细面试题(一)集合
长安不及十里 - 2021最详细面试题(二)多线程
长安不及十里 - 2021最详细面试题(三)面向对象
长安不及十里 - 面试题总结(五)JVM基本知识
长安不及十里 - 2021最详细面试题(四)JavaWeb
长安不及十里 - 2021最详细面试题(五)Mysql
长安不及十里 - 2021最详细面试题(六)Mybatis
长安不及十里 - 2021最详细面试题(七)Spring
长安不及十里 - 2021最详细面试题(八)SpringMvc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值