1.HashMap和ConcurrentHashMap区别
安全机制不同:hashMap是线程不安全的,在扩容时可能会造成死循环,在put的时候造成数据丢失;ConcurrentHashMap在jdk1.7采用了锁分离机制保证了线程安全,jdk1.8中采用CAS+synchronized 保证线程安全。
扩展:
构成上:jdk1.8之前,hashmap使用Entry,数组+链表构成;jdk1.8之后使用node,数组+链表+红黑树构成,减少了查找时间。
处理冲突方式:HashMap在jdk1.7之前存储时出现冲突后链表插入采用头插法,头插法可能会造成死循环;jdk1.8之后存储时出现冲突时链表插入采用尾插法,当链表长度超过8时,使用红黑树存储数据;
ConcurrentHashMap的CAS机制,CAS的全称是Compare And Swap 即比较交换,参数为CAS(V,E,N),CAS是需要结合voliate使用的
function cas(V : pointer to int, E : int, N: int) returns bool {
if *V ≠ E{
return false
}
*V <- new
return true
}
该方法首先判断是否为当前线程,如果是,则修改当前线程里的变量。否则则继续等待,直到等到当前线程。
但是CAS里面的参数,我从网上看了一下,感觉说的都说不到点儿上,我个人认为的V轮询到的线程,E的话是指定的线程,N的话是要更新的值。欢迎留言赐教
2.介绍一下maven
maven是项目管理工具,里面的pom.xml负责记录当前所用的jar包的引用、版本等,不用将jar包下载到本地即可启动项目,通过依赖注入配置当前系统。支持springboot项目打包,maven的四大特性:
- 依赖管理系统
- 多模块构建
- 一致的项目结构
- 一致的构建模型和插件机制
3.Springboot启动必备依赖
1.<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
(1)定义了 Java 编译版本为 1.8 。
(2)使用 UTF-8 格式编码。
(3)继承自 spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所 以我们在写依赖时才不需要写版本号。
(4)执行打包操作的配置。
(5)自动化的资源过滤。
(6)自动化的插件配置。
(7)针对 application.properties 和 application.yml 的资源过滤,包括通过 profile 定义的不同环境的配置文件,例如 application-dev.properties 和 application-dev.yml。
2.<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(1)web的场景,自动帮我们引入了web模块开发需要的相关jar包,包含Tomcat配置,hibernate,使得当前配置可以自启动
3.<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
(1)maven依赖
4.Spring常用注解
@AutoConfig 自动配置
@Service service类,引用时无需初始化
@Controller 控制类,可以接收外部访问
@Component 自动装配
@Data 实体类的getter/setter
@Autowired 自动装配,无需初始化类
@ConfigurationProperties 加载yml文件配置
5.ConcurrentHashmap的CAS机制(参考1)
6.线程池ExecutorPool
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue);
参数详解:
corePoolSize:核心线程池的线程数量
maximumPoolSize:最大的线程池线程数量
keepAliveTime:线程活动保持时间,线程池的工作线程空闲后,保持存活的时间。
unit:线程活动保持时间的单位。
workQueue:指定任务队列所使用的阻塞队列
keepAliveTime:表示空闲线程的存活时间。
TimeUnitunit:表示keepAliveTime的单位。
handler:表示当workQueue已满,且池中的线程数达到maximumPoolSize时,线程池拒绝添加新任务时采取的策略。有四种拒绝策略
线程池用法:
(1) 如果没有空闲的线程执行该任务且当前运行的线程数少于corePoolSize,则添加新的线程执行该任务。
(2) 如果没有空闲的线程执行该任务且当前的线程数等于corePoolSize同时阻塞队列未满,则将任务入队列,而不添加新的线程。
(3) 如果没有空闲的线程执行该任务且阻塞队列已满同时池中的线程数小于maximumPoolSize,则创建新的线程执行任务。
(4) 如果没有空闲的线程执行该任务且阻塞队列已满同时池中的线程数等于maximumPoolSize,则根据构造函数中的handler指定的策略来拒绝新的任务。
(5) 当空闲线程超出keepAliveTime规定的时间后,则停止当前线程
(6) handle的拒绝策略如下:
ThreadPoolExecutor.AbortPolicy() | 抛出RejectedExecutionException异常 |
ThreadPoolExecutor.CallerRunsPolicy() | 由向线程池提交任务的线程来执行该任务 |
ThreadPoolExecutor.DiscardOldestPolicy() | 抛弃最旧的任务(最先提交而没有得到执行的任务) |
ThreadPoolExecutor.DiscardPolicy() | 抛弃当前的任务 |
7.Spring 的IOC和AOP
IOC:控制反转,IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
ApplicationContext是IOC的核心.
如下使用:
<bean name="stu" class="com.domain.Student"></bean>
<bean name="teacher" class="com.domain.Teacher">
<property name="stu" ref="stu"></property>
</bean>
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Teacher tea=(teacher) ctx.getBean("teacher");
}
AOP:AOP是Spring框架面向切面的编程思想,AOP采用一种称为“横切”的技术,将涉及多业务流程的通用功能抽取并单独封装,形成独立的切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。
基本概念:
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
通知方法:
前置通知:在我们执行目标方法之前运行(@Before)
后置通知:在我们目标方法运行结束之后 ,不管有没有异常(@After)
返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
环绕通知:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知, 执行之后就相当于我们后置通知(@Around)
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
8.介绍一下redis(这个我也了解的不多,后面熟悉了再具体写)
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
9.git和svn的区别
(1) GIT是分布式的,SVN不是
(2) GIT把内容按元数据方式存储,而SVN是按文件
(3) GIT分支和SVN的分支不同
(4) GIT没有一个全局的版本号,而SVN有
(5) GIT的内容完整性要优于SVN
10.介绍一下索引以及如何建索引
(1) 索引是一种指针,结构是B+tree,用于提高数据库表查询速度。
(2) 建立索引的方式
a.建索引语句:
create index 索引名 on 表名 (字段);
alter table 表 add index 索引名 (字段)
-- 普通索引
alter table 表名 add index 索引名 (字段) ;
-- 唯一索引
alter table 表名 add unique (字段) ;
-- 主键索引
alter table 表名 add primary key (字段) ;
drop index 索引名 on 表名;
b.建索引的方式
单列索引(使用索引时模糊查询不能将%放在左侧;如果使用多个单列索引中包含主键索引,则只会使用主键索引)
组合索引(查询时要符合最左原则)
11.JVM调优
JVM 内存布局规定了 Java 在运行过程中内存申请、分配、管理的策略 ,保证了 JVM 的高效稳定运行。
关于jvm调优的几款工具
- Jconsole:jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用,对垃圾回收算法有很详细的跟踪
- Jprofiler:功能强大,付费
- VisualVM:jdk自带,功能强大。
调优经验(参考https://blog.csdn.net/weixin_42447959/article/details/81637909)
- 避免创建过大的对象及数组:过大的对象或数组在新生代没有足够空间容纳时会直接进入老年代,如果是短命的大对象,会提前出发Full GC。
- 避免同时加载大量数据,如一次从数据库中取出大量数据,或者一次从Excel中读取大量记录,可以分批读取,用完尽快清空引用。
- 当集合中有对象的引用,这些对象使用完之后要尽快把集合中的引用清空,这些无用对象尽快回收避免进入老年代。
- 可以在合适的场景(如实现缓存)采用软引用、弱引用,比如用软引用来为ObjectA分配实例:SoftReference objectA=new SoftReference(); 在发生内存溢出前,会将objectA列入回收范围进行二次回收,如果这次回收还没有足够内存,才会抛出内存溢出的异常。
- 避免产生死循环,产生死循环后,循环体内可能重复产生大量实例,导致内存空间被迅速占满。
- 尽量避免长时间等待外部资源(数据库、网络、设备资源等)的情况,缩小对象的生命周期,避免进入老年代,如果不能及时返回结果可以适当采用异步处理的方式等。
12.jdk1.8的特性
- lamda表达式,替代for循环,使用流的方式遍历集合
- 接口中可以定义默认实现方法和静态方法:在接口中可以使用default和static关键字来修饰接口中定义的普通方法
- ConcurrentHashMap添加CAS支持多线程安全
- JVM机制添加元数据区,主要用来保存被虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。
- Object.equals比较两个值是否相等,支持空值比较
13.Spring和Springboot区别
- Spring是一种框架,利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。
- Springboot是一种轻量级框架,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。
14.Linux命令
- 编辑:vim
- 查看文件列表:ls或者ll
- 压缩文件:tar
- 进入目录:cd
- 复制命令:cp
15.如何部署项目(Springboot在linux下部署)
- 因为Springboot自带Tomcat,所以可以直接执行java -jar package.jar包命令执行
16.高并发(这个不太了解,参考链接:https://blog.csdn.net/weixin_42476601/article/details/82220027)
高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展。
互联网分层架构中,各层次水平扩展的实践又有所不同:
(1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展;
(2)站点层可以通过nginx来进行水平扩展;
(3)服务层可以通过服务连接池来进行水平扩展;
(4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;
各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限。
17.dubbo
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
主要核心部件:
Remoting: 网络通信框架,实现了 sync-over-async 和request-response 消息机制.
RPC: 一个远程过程调用的抽象,支持负载均衡、容灾和集群功能
Registry: 服务目录框架用于服务的注册和服务事件发布和订阅
18.如何使用idea中的debugger(一般人都会打debug,就不介绍了,百度吧)
19.介绍一下自身优势
喜欢钻研,热爱技术。。。此处略去一万字
这是我想起来的面试题,大致都能答出来,但是不够深入,如果都能介绍到底层原理的话,应该是加分项
答案的话,比较浅显,真正的还是要知道原理的。改了好几次排版,但是发布成功一看还是有点儿鳞次栉比。。有错误欢迎大佬指正!