面试专题

文章目录

在这里插入图片描述

在阿里巴巴干了四年的Java面试官,知道我最常问的面试题是什么吗?

java基础

Object类都有哪些方法?

11种。线程调度5种;类相关getClass、clone;比较相关equals、hashcode、tostring;垃圾回收finalize。
Object类有哪些方法?各有什么作用?

String字符串拼接的多种方式

Java中的+对字符串的拼接,其实现原理是使用StringBuilder.append。
字符串拼接常用方法

泛型(? extend T)&(? super T)

子读父写。
(? extend T)集合仅可读;(? super T)集合仅可写。

NIO

JDK10都发布了,nio你了解多少?

集合

Iterator 和 ListIterator 有什么区别?

一.相同点
都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。
二.不同点
1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。
2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。
3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。
4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

怎么确保一个集合不能被修改?

final关键字可以修饰类,方法,成员变量,final修饰的类不能被继承,final修饰的方法不能被重写,final修饰的成员变量必须初始化值,如果这个成员变量是基本数据类型,表示这个变量的值是不可改变的,如果说这个成员变量是引用类型,则表示这个引用的地址值是不能改变的,但是这个引用所指向的对象里面的内容还是可以改变的。

我们可以采用Collections包下的unmodifiableMap方法,通过这个方法返回的map,是不可以修改的。他会报 java.lang.UnsupportedOperationException错。
同理:Collections包也提供了对list和set集合的方法。
Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)

hashmap源码

HashMap源码

hashmap和hashtable的区别

①线程安全角度;②执行效率角度;③对null的支持,hashtable的key和value都不可以为null;④初始容量和扩容机制:hashtable初始容量指定多少就是多少,扩容变成原长度的2n+1,hashmap初始容量会根据用户输入扩充为2的幂次方,扩容变成原长度的2倍;⑤底层数据结构:jdk1.8后hashmap引入了红黑树,hashtable没有。

ConcurrentHashMap和CopyOnWriteArrayList的底层实现

CopyOnWriteArrayList:读的时候不加锁,写的时候复制数组内容,进行写操作,最后把指针指向新数组,解锁。适合读多写少的场景。
ConcurrentHashMap:jdk1.8之后取消了分段锁,使用CAS进行并发控制,只锁对应的链表头,细化了锁的粒度,进一步减少并发冲突。
CopyOnWriteArrayList与ConcurrentHashMap原理解析

Optional

Optional类的优势:使用Optional类进行非空判断。代码行数与null判断基本相同。好处有:①实现了函数式接口,可以使用lamda简化代码写法;②可以链式调用。
opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));
Optional.ofNullable()创建optional对象,通过filter、map等方法得到的对象一定不是null,后续可以通过orElse()、orElseGet()、orElseThrow()方法处理null值。
理解、学习与使用 JAVA 中的 OPTIONAL

多线程

并行和并发

并发:不同的代码块交替执行
并行:不同的代码块同时执行
并发的反义是顺序,并行的反义是串行。并发并行并不是互斥概念,只不过并发强调任务的抽象调度,并行强调任务的实际执行。

线程和进程

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。
与进程不同的是同类的多个线程共享进程的方法区资源,但每个线程有自己的程序计数器虚拟机栈本地方法栈
所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

线程有哪些状态

在这里插入图片描述

线程的 run()和 start()有什么区别?

new 一个 Thread,线程进入了新建状态;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run 方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。

创建线程池有哪几种方式?

我们可以创建三种类型的ThreadPoolExecutor:

  • FixedThreadPool : 该方法返回一个固定线程数量的线程池。
  • SingleThreadExecutor: 方法返回一个只有一个线程的线程池(先入先出执行)。
  • CachedThreadPool: 该方法返回一个可根据实际情况调整线程数量的线程池。
线程池都有哪些状态?

在这里插入图片描述

线程池中 submit()和 execute()方法有什么区别?
  1. execute()`方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功与否;**
  2. submit()方法用于提交需要返回值的任务。线程池会返回一个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执行成功.
多线程锁的升级原理是什么?

无锁:没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。
偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,该线程在后续的执行中自动获取锁,降低获取锁带来的性能开销。偏向锁,指的就是偏向第一个加锁线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。
轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B 会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。

当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。
重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

说一下 synchronized 底层实现原理?

在这里插入图片描述
monitorenter :
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
monitorexit: 
指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。

synchronized 和 volatile 的区别是什么?

(1)、volatile只能作用于变量,使用范围较小。synchronized可以用在变量、方法、类、同步代码块等,使用范围比较广。
(2)、volatile只能保证可见性和有序性,不能保证原子性。而可见性、有序性、原子性synchronized都可以保证。
(3)、volatile不会造成线程阻塞。synchronized可能会造成线程阻塞。

synchronized 和 Lock 有什么区别?

来源
lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;
异常是否释放锁
synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)
是否响应中断
lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;
是否知道获取锁
Lock可以通过trylock来知道有没有获取锁,而synchronized不能;
Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度。

synchronized 和 ReentrantLock 区别是什么?

synchronized 竞争锁时会一直等待;ReentrantLock 可以尝试获取锁,并得到获取结果
synchronized 获取锁无法设置超时;ReentrantLock 可以设置获取锁的超时时间
synchronized 无法实现公平锁;ReentrantLock 可以满足公平锁,即先等待先获取到锁
synchronized 控制等待和唤醒需要结合加锁对象的 wait() 和 notify()、notifyAll();ReentrantLock 控制等待和唤醒需要结合 Condition 的 await() 和 signal()、signalAll() 方法
synchronized 是 JVM 层面实现的;ReentrantLock 是 JDK 代码层面实现
synchronized 在加锁代码块执行完或者出现异常,自动释放锁;ReentrantLock 不会自动释放锁,需要在 finally{} 代码块显示释放

说一下 atomic 的原理?

JDK Atomic开头的类,是通过 CAS 原理解决并发情况下原子性问题。
CAS 包含 3 个参数,CAS(V, E, N)。V 表示需要更新的变量,E 表示变量当前期望值,N 表示更新为的值。只有当变量 V 的值等于 E 时,变量 V 的值才会被更新为 N。如果变量 V 的值不等于 E ,说明变量 V 的值已经被更新过,当前线程什么也不做,返回更新失败。
当多个线程同时使用 CAS 更新一个变量时,只有一个线程可以更新成功,其他都失败。失败的线程不会被挂起,可以继续重试 CAS,也可以放弃操作。
CAS 操作的原子性是通过 CPU 单条指令完成而保障的。JDK 中是通过 Unsafe 类中的 API 完成的。
在并发量很高的情况,会有大量 CAS 更新失败,所以需要慎用。

线程池源码

线程池其实看懂了也很简单

线程的sleep、wait、yield、join

sleep:阻塞线程,不会释放锁,使用时抛出异常;
wait:阻塞线程,会释放锁,在同步代码块中使用,使用时不抛异常;
yield:当前正在执行的线程让出cpu,重回就绪状态, yield 方法只能使同优先级或更高优先级的线程有执行的机会;
join:等待调用join方法的线程结束之后,程序再继续执行,一般用于等待异步线程执行完结果之后才能继续运行的场景。
浅谈sleep、wait、yield、join区别

spring的@EnableAsync

本质上就是使用spring封装好的ThreadPoolTaskExecutor,以注解的形式使用多线程。
【Springboot】——@EnableAsync@Async

Executors创建四种线程池

使用Executors创建四种线程池

ThreadLocal

从名字我们就可以看到ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
ThreadLocal 内存泄露问题(与强弱引用无关)

在这里插入图片描述

CountDowmLatch、CyclicBarrier
  • CyclicBarrier的计数器由自己控制,而CountDownLatch的计数器则由使用者来控制,在CyclicBarrier中线程调用await方法不仅会将自己阻塞还会将计数器减1,而在CountDownLatch中线程调用await方法只是将自己阻塞而不会减少计数器的值。
  • CountDownLatch只能拦截一轮,而CyclicBarrier可以实现循环拦截。一般来说用CyclicBarrier可以实现CountDownLatch的功能,而反之则不能,例如上面的赛马程序就只能使用CyclicBarrier来实现。总之,这两个类的异同点大致如此,至于何时使用CyclicBarrier,何时使用CountDownLatch,还需要读者自己去拿捏。
  • 除此之外,CyclicBarrier还提供了:resert()、getNumberWaiting()、isBroken()等比较有用的方法。
    深入理解CyclicBarrier原理

redis

zset数据结构

redis zset底层数据结构

jedis、redission、lettuce区别
  • Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。
  • Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。
  • Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作。
  • 优先使用Lettuce,如果需要分布式锁,分布式集合等分布式的高级特性,添加Redisson结合使用,因为Redisson本身对字符串的操作支持很差。
RedisTemplate的Api

RedisTemplate操作Redis,这一篇文章就够了(一)

缓存穿透、缓存击穿、缓存雪崩

缓存穿透、缓存击穿、缓存雪崩区别和解决方案

redis实现分布式锁

Redis分布式锁的正确实现方式

网络

说一下 tcp 粘包是怎么产生的?

TCP粘包原理及解决方案

浏览器输入 URL 发生了什么?

在这里插入图片描述

tcp/ip的三次握手四次分手

计算机网络——五层参考模型

http的请求、响应报文格式

HTTP请求、响应报文格式

操作系统(内存管理是重点)

我和面试官之间关于操作系统的一场对弈!写了很久,希望对你有帮助!

Spring

解释一下什么是 ioc?

IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spring 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。

解释一下什么是 aop?

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性
Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib

spring 中的 bean 是线程安全的吗?

Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。
Spring 的 bean 作用域(scope)类型
1、singleton:单例,默认作用域。
2、prototype:原型,每次创建一个新对象。
3、request:请求,每次Http请求创建一个新对象,适用于WebApplicationContext环境下。
4、session:会话,同一个会话共享一个实例,不同会话使用不用的实例。
5、global-session:全局会话,所有会话共享一个实例。
线程安全这个问题,要从单例与原型Bean分别进行说明。
原型Bean
  对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。
单例Bean
  对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

spring bean的生命周期

关于Spring Bean的生命周期

springboot的自动化配置原理

Spring Boot面试杀手锏————自动配置原理

spring三级缓存解决循环依赖

Spring中的循环依赖解决详解

springcloud各组件详解

大白话入门 Spring Cloud

MySQL

在这里插入图片描述

MySql索引分类、数据结构、优化细节
【收藏】写给程序员的 MySQL 高频面试题!
为什么 Mongodb 索引用 B 树,而 Mysql 用 B+ 树?
在这里插入图片描述

JVM

面试官:JVM调优的常用基本配置参数有哪些?

RocketMQ

RocketMQ在面试中那些常见问题及答案+汇总

Linux

Linux常见问题定位

手把手教你定位常见Java性能问题

面经

美团面试常见问题总结

算法书

《程序员代码面试指南 IT名企算法与数据结构题目最优解 ,左程云著 ,P513》
链接:https://pan.baidu.com/s/1c6iyckmlztHOz-uhiy6ffQ
提取码:2sgv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值