每天十道面试题-20200324 - 日理万妓 2023-07-18 06:18 36阅读 0赞 ### 每天十道面试题-20200324 ### * * * * 题目 * 解答 * * * 题目一 * 题目二 * 题目三 * 题目四 * 题目五 * 题目六 * 题目七 * 题目八 * 题目九 * 题目十 #### 题目 #### * 1、Java容器有哪些?哪些是同步容器,哪些是并发容器? * 2、ArrayList和LinkedList的插入和访问的时间复杂度? * 3、HashMap检测到hash冲突后,将元素插入在链表的末尾还是开头? * 4、新生代分为几个区?使用什么算法进行垃圾回收?为什么使用这个算法? * 5、1.8还采用了红黑树,讲讲红黑树的特性,为什么人家一定要用红黑树而不是AVL、B树之类的? * 6、两个线程,一个线程打印奇数,一个打印偶数,控制交替打印奇偶数 * 7、线程池的工作原理,几个重要参数,然后给了具体几个参数分析 * 8、线程池会怎么做,最后问阻塞队列的作用是什么? * 9、https和http区别,有没有用过其他安全传输手段? * 10、有没有了解 Spring 的原理?AOP 和 IOC 的原理 #### 解答 #### ###### 题目一 ###### * 题干:Java容器有哪些?哪些是同步容器,哪些是并发容器? * 分析: * > Java中的容器主要分为Collection和Map两类,Collection中又主要包括Set和List,常见的有HashSet、ArrayList、HashMap,同步容器指的是使用synchronized来达到线程安全的容器,synchronized是一种悲观的、不公平的、重量级【是指调用操作系统接口】的锁,而并发容器是用于并发环境的,一般采用CAS、COW、分段锁、LOCK来实现。 * 回答: * > Java中容器主要包括Set 、List、Map这三种,同步容器有:HashTable、Vector、Stack以及Collections工具类得到的同步容器如:Map map = Collections.synchronizedMap(new HashMap()); > 并发容器有:CopyOnWriteArrayList、ConcurrentHashMap等。 ###### 题目二 ###### * 题干:ArrayList和LinkedList的插入和访问的时间复杂度? * 分析: * > 这个题主要是考察数组和链表的区别,我们需要知道时间复杂度的计算。 * 回答: * > ArrayList get方法获取直接使用index进行访问时间复杂度O\[1\], > add 方法直接追加在数组最后O\[1\],使用index指定追加的位置这时时间复杂度O\[n\],LinkListget方法获取需要遍历链表所以是O\[n\],直接add一般追加在尾部,所以是O\[1\],add指定添加在某个元素之后,这个时间复杂度O\[n\]. ###### 题目三 ###### * 题干:HashMap检测到hash冲突后,将元素插入在链表的末尾还是开头? * 分析: * > 这个猜测是想问Hash Map的死循环问题,在jdk1.8之前是采用的头插法,在多线程环境下Hash Map在rehash时会改变链表的元素顺序【逆序】,所以会出现环【但是多线程环境下为什么要用HashMap直接用CourrentHashMap就行了】。 * 回答: * > jdk1.8之前采用的时头插法,可能会产生死循环,前提时多线程环境发生reHash,jdk1.8之后改为尾插法。 ###### 题目四 ###### * 题干:新生代分为几个区?使用什么算法进行垃圾回收?为什么使用这个算法? * 分析: * > 主要考察JVM的垃圾回收机制以及回收算法。 * 回答: * > 新生代也就是我们常说的Young区,它分为Eden【伊甸区】,From区、To区【From和To也称之为Survivor区】,在经过第一次MinorGC时,存活的对象会移动到To区,然后From和To互换名字,如果发生第二次GC,那么Eden区存活的对象以及From区中的对象都会移动到To区,然后From和To互换名字,该部分使用复制算法,原因是:复制算法可以减少内存碎片,适用于对象少的垃圾回收,因为如果数量大移动时效率低,而垃圾回收对速度要求很高。 ###### 题目五 ###### * 题干:1.8还采用了红黑树,讲讲红黑树的特性,为什么人家一定要用红黑树而不是AVL、B树之类的? * 分析: * > 红黑树不追求"完全平衡" * 回答: * > 红黑树更适合于插入修改密集型任务,红黑树牺牲了一些查找性能 但其本身并不是完全平衡的二叉树。因此插入删除操作效率略高于AVL树 > AVL树用于自平衡的计算牺牲了插入删除性能 ###### 题目六 ###### * 题干:两个线程,一个线程打印奇数,一个打印偶数,控制交替打印奇偶数 * 分析: * > 自行解决 * 回答: * > 自行解决 ###### 题目七 ###### * 题干:线程池的工作原理,几个重要参数 * 分析: * > 之前看到一个线程池的连环问,根据这个连环问说一下: > 问题是这样的: > 了解JDK Executors线程池吗? > 知道JDK提供了哪些默认的实现吗? > 看过阿里巴巴java开发手册吗?知道为啥不允许使用默认的实现吗? > 你们没有用默认的吧?那来介绍一下你们自定义线程池的几个常用参数呗? > 你这个几个参数的值是怎么得来的呀?算出来的?怎么算出来的? > 算出来之后,现在我们有一个自定义线程池了,来说一下你这个线程池的工作流程呗? > 那你这个线程池满了怎么办呀?拒绝?咋拒绝?有哪些拒绝策略呢? > 这个第一个问题不了解也得说了解,你要真是不了解那就继续看. > 第二个问题在回答之前,先说点别的,首先jdk给我们提供了个工具类Executors(你看这个名字叫的,是不是和Collections Arrays很像)所以他就是个厂子,而主角是Executor接口它只定义了一个方法excute(),而 > ExecutorService这个接口extends Executor添加了生命周期的相关方法,现在我们说了一个工具类和两个两个接口,而真正干事的是ThreadPoolExecutor 这个类,而对于提供的默认实现指的是Executors工具中的常用的四种静态方法newSingleThreadExecutor() newFixedThreadPool(int nThreads) newCachedThreadPool() newSingleThreadExecutor(),这四个默认的实现.(看名字就知道 干嘛的了). > newFixedThreadPool(int Threads):创建固定数目的线程池。 > newSingleThreadPoolExecutor():创建一个单线程的线程池。 > newCacheThreadPool():创建一个可缓存的线程池,调用execute将重用以前构成的线程。 > newScheduledThreadPool(int corePoolSize):创建一个支持定时及周期性的任务执行的线程池。 > 常用的方法是newFixedThreadPool和newCacheThreadPool。 > 第三个问题,看没看过不重要,反正需要知道不建议使用默认实现,而且一般不建议自己显示的创建线程,对于线程应该交给线程池创建管理,原因是,这四个静态方法其实底层都是调用的ThreadPoolExecutor的有参构造函数进行创建ThreadPoolExecutor,用Executors默认方法创建线程池,会允许创建最大长度为Integer.MAX\_VALUE如果有大量的请求,会导致OOM,在创建LinkedBlockingQueue时,并未指定容量。此时,LinkedBlockingQueue就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,就有可能因为任务过多而导致内存溢出的问题。 > newSingleThreadExecutor() newFixedThreadPool(int nThreads)允许的请对队列长度为Integer.MAX\_VALUE,如果堆积大量的请求就会导致OOM, > newCachedThreadPool() newScheduledThreadPool()允许创建的最大线程数是Integer.MAX\_VALUE从而导致OOM. > 第四个问题:常用参数 > corePoolSize: 线程池维护线程的最少数量 (core : 核心) > maximumPoolSize: 线程池维护线程的最大数量 > keepAliveTime: 线程池维护线程所允许的空闲时间 > unit: 线程池维护线程所允许的空闲时间的单位 > workQueue: 线程池所使用的缓冲队列 > handler: 线程池对拒绝任务的处理策略 > 第五个问题,它要问你怎么算,很好,基本上是取决于CPU的核数,以及IO,数据库连接等,\[这么算\] > (https://blog.csdn.net/qq\_34417408/article/details/78895573?depth\_1-utm\_source=distribute.pc\_relevant.none-task&utm\_source=distribute.pc\_relevant.none-task) > 大概说一下啊: > 主要是分为IO密集型【磁盘IO密集型, 网络IO密集型,微服务网关就属于网络 IO 密集型,涉及大量数据库操作的就是磁盘密集型】还是CPU密集型【也就是计算密集型】,对于CPU密集型理论上根据物理CPU核数来决定【一个物理CPU可以有1个或者多个物理内核, > 一个物理内核可以作为1个或者2个逻辑CPU总的CPU物理内核数 = 物理CPU数 \* 每颗物理CPU的内核数总的逻辑CPU数 = 物理CPU个数 \* 每颗物理CPU的核数 \* 超线程数 > 总的逻辑CPU数 = 总的CPU物理内核数 \* 超线程数】,如果是CPU密集型理论上和物理内核数一致,这样充分利用CPU且无上下文切换损耗。如果是IO密集型那么可以考虑超过物理内核数或者逻辑内核数,但是具体多少需要实际测量 > 根据公式:最佳线程数量=CPU执行核心数/(1-阻塞系数) 这个阻塞系数取决于其他等待线程的数量和上下文切换时间,如果其他线程越多也就是你开启的线程总数占比总线程数越小那么阻塞系数越大,如果上下文切换时间越大则阻塞系数也越大,阻塞系数越大则分母越小则需要的最佳线程数越多【阻塞系数越大就越需要分配更多的线程去操作这样是为了更多的更大可能性的占用CPU的使用时间】。 > 第六个问题说工作流程 > 核心线程数未满,直接创建新的核心线程来执行任务,若有空闲线程,复用空闲线程 > 核心线程数已满,要执行的任务加入堵塞队列 > 核心线程数已满,堵塞队列已满,创建非核心线程来执行任务(非时序关联的流程,非核心线程若空闲,并且到达存活时间,会被回收),若有空闲线程,可复用 > 核心线程已满,堵塞队列已满,非核心线程已满,任务会被拒绝执行,调用RejectedExecutionHandler > 第七个拒绝策略ThreadPoolExecutor内部有四个类实现了RejectedExecutionHandler接口 > ThreadPoolExecutor.AbortPolicy > 被拒绝的任务的处理程序,抛出一个 RejectedExecutionException 。 > ThreadPoolExecutor.CallerRunsPolicy > 一个被拒绝的任务的处理程序,直接在 execute方法的调用线程中运行被拒绝的任务,除非执行程序已经被关闭,否则这个任务被丢弃。 > ThreadPoolExecutor.DiscardOldestPolicy > 被拒绝的任务的处理程序,丢弃最旧的未处理请求,然后重试 execute ,除非执行程序关闭,在这种情况下,任务被丢弃。 > ThreadPoolExecutor.DiscardPolicy > 被拒绝的任务的处理程序静默地丢弃被拒绝的任务。 * 回答: * > 参看分析部分 ###### 题目八 ###### * 题干:线程池会怎么做,最后问阻塞队列的作用是什么? * 分析: * * 回答: * ###### 题目九 ###### * 题干:https和http区别,有没有用过其他安全传输手段? * 分析: * > HTTPS在HTTP的基础上加入了SSL/TLS协议,依靠SSL证书来验证服务器的身份,并为客户端和服务器端之间建立“SSL加密通道”,确保用户数据在传输过程中处于加密状态,同时防止服务器被钓鱼网站假冒,而HTTP协议无法加密数据,所有通信数据在网络是明文。通过网络的一些技术手段,就可还原HTTP报文内容。 * 回答: * > (1)HTTP 是超文本传输协议,属于明文传输协议,HTTPS 则是具有安全性的基于ssl加密的传输协议 > (2)HTTP 和 HTTPS 使用的是连接方式不同,而且用的端口也不一样,前者是80,后者是443。 > (3)HTTP 是简单的无状态的连接。HTTPS 协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比 HTTP 协议安全 > (4)HTTPS 内容经过对称加密,每个连接生成一个唯一的加密密钥(对称秘钥:对称密钥加密又叫专用密钥加密,即发送和接收数据的双方必使用相同的密钥对明文进行加密和解密运算。) > (5)HTTPS 内容传输经过完整性校验 ###### 题目十 ###### * 题干:有没有了解 Spring 的原理?AOP 和 IOC 的原理 * 分析: * > AOP 和 IOC * 回答: * > IOC 是工厂模式为主 > 通过 读取配置文件 使用反射获取JavaConfig 或者使用注解@Autowaire @Resource 的类读取这些Bean 将其映射撑BeanDefined对象,将其放在使用BeanDefineRegistry将所有扫描到的bean放到注册的Bean列表里,然后创建Bean实例,如果是单例的Bean就放在Bean的缓存池里池子里是一个Map对象 key是类名 value是bean的实例对象。多例的直接返回给调用者。 > AOP 主要是代理模式 使用的是jdk动态代理【实现接口】、cglib【实现类】动态代理。静态AOP代理 Aspect J 是使用自己的类 直接硬编码 所以编译的时候直接就生成class文件了,所以这个是静态的 > 动态的AOP代理, jdk、cglib 一个是使用反射一个是通过asm动态字节码工具来实现的。
相关 前端—每天5道面试题(十) 前端—每天5道面试题(十) > 每天进步1% 不多 就1% ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow 末蓝、/ 2023年01月23日 11:58/ 0 赞/ 36 阅读
相关 前端—每天5道面试题(十四) 前端—每天5道面试题(十四) > 每天进步1% 不多 就1% ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_sha 淡淡的烟草味﹌/ 2022年08月30日 01:42/ 0 赞/ 228 阅读
还没有评论,来说两句吧...