前言
最近大家应该都在是否要选择更好的公司而发愁,而又怕面试没有准备充分错失机会,那么这篇文章希望可以帮到你。
一名Java后端在重庆面试亲身经历,每一场面试脑海中印象比较深刻的问题记录下来,并且总结,找出答案,分享出来。 现在面试问的问题都相对来说比较深入
话不多说上题目:
JWT使用
客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。
此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。
Authorization: Bearer
当跨域时,也可以将JWT被放置于POST请求的数据主体中。
token是如何生成
微服务链路检测
链路追踪
SkyWalking or Zipkin
ZipKin:服务调用的请求和响应中加入ID,标明上下游请求的关系。利用这些信息,可以可视化地分析服务调用链路和服务间的依赖关系
Spring Cloud Sleuth是对Zipkin的一个封装,对于Span、Trace等信息的生成、接入HTTP Request,以及向Zipkin Server发送采集信息等全部自动完成。
参考博文:
www.cnblogs.com/duanxz/p/75… www.cnblogs.com/duanxz/p/75…
泛型的实现
泛型的实现是靠类型擦除技术, 类型擦除是在编译期完成的, 也就是在编译期, 编译器会将泛型的类型参数都擦除成它的限定类型,如果没有则擦除为object类型之后在获取的时候再强制类型转换为对应的类型。 在运行期间并没有泛型的任何信息,因此也没有优化。
cglib的实现
动态代理
有哪些开发规范
REST full
你对雪崩效应的看法
看过哪些源代码
熔断器的使用
在启动类中,需要添加 @EnableCircuitBreaker 注解 定义 Hystrix 处理类
OrderClientServiceFallbackFactory implements FallbackFactory<OrderClientService>
重写 create方法 里面再重写熔断的默认返回 配合feign在接口上面加上工厂类
@FeignClient(value = "MICROSERVICE-ORDER", fallbackFactory = OrderClientServiceFallbackFactory.class)
开启熔断
feign:
hystrix:
enabled: true
高并发场景
服务器方面
nginx 使用负载均衡
使用服务器集群
业务实现方面
使用队列Kafka、RabitMQ等
处理秒杀 抢购等高并发场景保证数据安全
使用缓存Redis、Memcache等
尽量使用缓存,包括用户缓存,信息缓存等,可以大量减少与数据库的交互,提高性能。
使用多线程
部分功能使用多线程后台执行 不阻塞主线程
数据库方面
优化数据库查询语句
优化数据库结构,多做索引,提高查询效率
统计相关功能最好定时统计,避免实时查询
代码方面
代码构造的时候尽量避免不必要的资源浪费,提高性能
如:不要频繁使用new对象 使用单例模式等
string的连接操作,使用stringbuffer(速度慢,线程安全)或者stringbuilder(速度快,线程不安全)
utility类型的类通过静态方法来访问
mybatis一级缓存,二级缓存
- 一级缓存:mybatis每次在查询后,会将语句和参数相同的查询SQL的结果集存放进缓存,待下一次有相同的语句和参数时,mybatis直接将缓存内的结果集返回,而不再查询数据库。
- 二级缓存:需要手动开启。一级缓存在同一个SqlSession内,以SqlSession为缓存单位;二级缓存在不同的SqlSession间,以mapper为单位,不同的SqlSession间可以共享相同的mapper下接口查询的数据
docker (k8s)
docker-compose
JVM调优
XX:MetaspaceSize=128m (元空间默认大小)
XX:MaxMetaspaceSize=128m (元空间最大大小)
Xms1024m (堆最大大小)
Xmx1024m (堆默认大小)
Xmn256m (新生代大小)
Xss256k (棧最大深度大小)
XX:SurvivorRatio=8 (新生代分区比例 8:2)
XX:+UseConcMarkSweepGC (指定使用的垃圾收集器,这里使用CMS收集器)
XX:+PrintGCDetails (打印详细的GC日志)
springcloud用过什么组件
- spring cloud eureka : 注册中心,可以看到各个服务运行状态,并且各个微服务调用都通过注册中心来找到内网ip进行调用
- spring cloud gateway: 对外的网关,分为zuul版本和F版本,两者最大区别是底层容器不同,zuul版本是servlet,F版本的是webFlux框架,并且F版本可设置统一过滤器,单个微服务过滤器,限流过滤器,相同的是都有负载均衡,熔断机制,重试规则
- spring cloud config: 配置中心,可以分为本地扫描配置和从git仓库拉取缓存,在spring cloud bus的配合下,可实现实时动态刷新配置文件
- spring cloud bus: 消息总线z,实现各个微服务之间的通信,整合java消息的发送和接收
- spring cloud Ribbon: 负载均衡
- spring cloud Feign: PRC 远程服务调用
- spring cloud Hystrix: 熔断机制
- spring cloud zipkin: 链路追踪,分为http追踪和rabbitmq追踪,提供前端页面显示各个接口之间的复杂的互相调用
- spring boot admin: 显示各个服务运行的详细状态,线程池,内存环境,系统环境属性,spring各种bean运行状态,可以把阿里数据库连接池druid的监控结合到了监控页面,可以监控到各个sql执行时间等等
- spring cloud oauth2: 鉴权服务, 四种模式: 用户名密码模式, 客户端模式, 授权码模式,简化模式过于复杂. 说明一下,目前微服务一般是使用Spring Cloud Alibaba 阿里开源组件
- Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
- Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
- RocketMQ:开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
- Dubbo:这个就不用多说了,在国内应用非常广泛的一款高性能 Java RPC 框架。
- Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
- Arthas:开源的Java动态追踪工具,基于字节码增强技术,功能非常强大。
CAP理论(C——数据一致性,A——服务可用性,P——服务对网络分区故障的容错性),
Euraka 和 dubbo ,zookeeper
- Euraka: 是分布式系统中的AP
- dubbo的注册中心一般选用zookeeper: zookeeper保证的是cp
- 在P在网络分区发生故障的时候,zookeeper 要进行选举,euraka: 可以快速切换到另外一个节点
java反射原理
jvm在运行过程中载入class文件,得到class对象后反向获取对象的各种信息
zookeeper 调用流程处理方法,调用方式
微服务调用元素
Java浅拷贝和深拷贝的理解和实现方式
浅拷贝(浅复制、浅克隆):
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
换言之,浅拷贝仅仅复制所拷贝的对象,而不复制它所引用的对象。
深拷贝(深复制、深克隆):
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
换言之,深拷贝把要复制的对象所引用的对象都复制了一遍
java悲观锁和乐观锁区别
定义:
悲观锁(Pessimistic Lock):
每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁。由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待。
乐观锁(Optimistic Lock):
每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。
适用场景:
悲观锁:比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。
乐观锁:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。
总结:两种所各有优缺点,读取频繁使用乐观锁,写入频繁使用悲观锁。
后端实现跨域
- spring就用filter里面往header里面放跨域参数
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
- Springboot 很简单 @CrossOrigin
- 或者用nginx实现做代理
Spring Boot、Spring MVC、Spring之间的区别?(Spring Boot本质是什么?)
Spring Boot Starter 是什么?
如何自定义Spring Boot Starter?(如何扩展Spring Boot)
Spring Boot 的自动装配原理是什么?(源码分析哦)
在全局配置的属性如:server.port等,
通过@ConfigurationProperties注解,
绑定到对应的XxxxProperties配置实体类上封装为一个bean,
然后再通过@EnableConfigurationProperties注解导入到Spring容器中。
Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到
META-INF/spring.factories配置文件中的所有自动配置类,
并对其进行加载,而这些自动配置类 都是以AutoConfiguration结尾来命名的,
它实际上就是一个JavaConfig形式的Spring容器配置类,
它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:
server.port,
Spring Boot 的启动流程是什么?
有没有看过 Spring Boot 源码?你觉得最神奇的地方是什么?
对服务注册中心的理解
我的理解很简单就是服务注册进来就把他记录下来,客户端需要用的时候就直接来查询
对网关的理解
TCP/IP 顾名思义就是一个网络到一个网络的关口
jvm 原理
- JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。
- java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,通过JVM将每一条指令翻译成不同平台机器码,通过特定平台运行。
你是怎么设计微服务
1·单一职责(Single Responsibility),一个服务应当承担尽可能单一的职责,服务应基于有界的上下文(bounded context,通常是边界清晰的业务领域)构建,服务理想应当只有一个变更的理由(类似Robert C. Martin讲的:A class should have only one reason to change),当一个服务承担过多职责,就会产生各种耦合性问题,需要进一步拆分使其尽可能职责单一化。
2·关注分离(Separation of Concerns),跨横切面逻辑,例如日志分析、监控、限流、安全等等,尽可能与具体的业务逻辑相互分离,让开发人员能专注于业务逻辑的开发,减轻他们的思考负担,这个也是有界上下文(bounded context)的一个体现。
3·模块化(Modularity)和分而治之(Divide & Conquer),这个是解决复杂性问题的一般性方法,将大问题(如单块架构)大而化小(模块化和微服务化),然后分而治之。
前期阶段,大致要做好如下事情:
和多方充分沟通,确保能符合客户和组织的需求,并且得到认同
和团队沟通,让队友(开发/测试/运维)理解,并且积极投入
和业务部门沟通,指定版本计划和上线时间
设计阶段,参考 Sam Newman 的著作《微服务设计》,单微服务必须要满足以下的条件,才符合微服务的基本要求:
标准的 REST 风格接口(基于 HTTP 和 JSON 格式)
独立部署,避免共享数据库(避免因为数据库而影响整个分布式系统)
业务上的高内聚,减少依赖(从设计上要避免服务过大或者太小)
技术阶段,庞大的分布式系统,需要强大基础设施来支撑,微服务涉及哪些基础设施?
CI/CD和自动化(分布式系统几乎不可能通过人工手动发布)
虚拟化技术(要保证微服务运行环境隔离,目前行业主流的是使用 Docker 容器)
日志聚合,全链路监控(高度可观察和分析诊断问题)
redis用过锁吗
redis缓存穿透 key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
redis雪崩 很多key在同一时间同时过期,解决方案就是把key分组,分别设置过期时间,避免同时过期的情况
redis内存优化
redis淘汰策略
(1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
(2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
(4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
(5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
(6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
(7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
(8) no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。
这八种大体上可以分为4中,lru、lfu、random、ttl。
Redis最为常用的数据类型主要有以下
String
Hash
List
Set
Sorted set 有序集合
redis 的应用场景
缓存,秒杀(expire过期时间),计数器(incrby命令可以实现原子性的递增),排行榜(SortedSet 排序),分布式锁(setnx命令进行,有过期时间,可防止死锁),延时操作,分页、模糊搜索(set集合中提供了一个zrangebylex方法),点赞、好友等相互关系的存储(set),队列
消息队列(rabbitMQ)
spring bean 不是线程安全的
普通的java类, 带有属性, 并且属性是可以被修改的, 那么这个类的实例就是有状态对象. 也就是如果你拿到的这个实例, 可能就被别人修改过, 那么你当前的操作就会受到别人之前操作的影响.
幂等性问题
微服务的架构设计
mybatis原理
通过 Resource加载 mapper.xml,生成一个 inputstream的输入流,创建 sqlsessionfactorybuilder对象,通过该对象的 builder( inputstream)方法,返回一个 sqlsessionfactory对象,由 sqlsessionfactory对象生成 sqlsession,通过 statement id找到对应的 statement,通过传入的参数进行一系列的复杂判断生成要执行的 sql,通过 jdbc执行 sql,然后把结果封装成 map、 list等返回
mybatis $ # 的区别
# 可以防止SQL注入 他会做字符串处理 他是预编译的,会用 ? 作为占位符
$ 的话就是你传什么他就是什么,他不会做字符串处理
TCP协议详解
1.第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
2.第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
3.第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
完成了三次握手,客户端和服务器端就可以开始传送数据。以上就是TCP三次握手的总体介绍。
java sync 锁的是什么
对象
hashmap的原理
(一个是链表的长度达到8个,一个是数组的长度达到64个)
数组加连表的结构 运用了红黑树原理
红黑树是什么
自平衡的二叉查找树。他这个自平衡的特性就是对HashMap中链表可能会很长做出的优化。
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
springboot的初始化原理
jvm的分区(五大分区)
程序计数器,虚拟机栈,本地方法栈,堆,方法区
GC垃圾回收机制
把所有对象组成一个集合,或可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到,这个对象就被回收了
工作原理
GC的工作流程主要分为如下几个步骤:
1、标记(Mark)---GC的根节点也即GC Root
2、计划(Plan)
3、清理(Sweep)
4、引用更新(Relocate)
5、压缩(Compact)
怎么执行GC垃圾回收
代码主动显式调用System.GC.Collect()
springboot是怎么实现springmvc的东西的
mysql怎么运用分库分表
两种解决方案:垂直拆分、水平拆分
- 垂直拆分:根据业务进行拆分,比如可以将一张表中的多个字段拆成两张表,一张是不经常更改的,一张是经常改的。
- 水平拆分:即根据表来进行分割:比如user表可以拆分为user0,、user1、user2、user3、user4等
用过哪些设计模式
工厂模式,单例模式(双检锁主要是加锁操作,先判断有没有对象,没有再创建),观察者模式。生产者消费者模式,动态代理模式
对Euraka服务注册中心的理解
Eureka 原理与步骤
比拟场景:餐厅吃饭
1、先向收银员(注册中心)要个号牌(IP地址)。
2、饭菜到场就根据你号牌(IP地址)将饭菜端到你面前。
3、在整个就餐过程中,你随时可以与收银员进行互相沟通(监听客户端心跳)。
4、最后你吃完跑路了号牌回收(剔除服务器)。
原理: 与比拟场景序号对应理解。
1、服务提供方启动后将注册到 注册中心,提供IP, 名字,什么服务等信息,
2、服务调用方作为客户端注册到注册中心后,拉取注册中心的服务列表,在通过负载均衡调用对应的服务提供方。
3、注册中心可以建立集群,生成多台eureka,注册中心为了监测各个服务的心跳,将在每30S 向所注册的服务发起请求判断
4、服务是否挂掉,如果挂掉90S后将会将服务从注册中心剔除。
一个服务可以监测多台服务实例,从而可实现均衡负载。
运用Euraka遇到的问题
zuul有哪些过滤器
a、pre: 这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务,记录调试信息等。
b、routing: 这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用apache httpclient或netflix ribbon请求微服务。
c、post: 这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的http header、收集统计信息和指标、将响应从微服务发送给客户端等。
e、error: 在其他阶段发送错误时执行该过滤器。
分页插件的好处是什么
封装类型和基本类型的区别
包装类型可以为 null,而基本类型不可以
包装类型可用于泛型,而基本类型不可以
基本类型比包装类型更高效
两个包装类型的值可以相同,但却不相等
自动装箱和自动拆箱
怎么解决并发的
消息队列,多线程,负载均衡,代码的话用一些 并发包,比如说map用ConcurrentHashmap
shrio的使用
Subject: 用户主体(把操作交给SecurityManager)
SecurityManager:安全管理器(关联Realm)
Realm:Shiro连接数据的桥梁
1·创建ShiroFilterFactoryBean
设置安全管理器 securityManager
添加Shiro内置过滤器(访问权限 anon: 无需认证(登录)可以访问 uthc: 必须认证才可以访问 user: 如果使用rememberMe的功能可以直接访问 perms: 该资源必须得到资源权限才可以访问
role: 该资源必须得到角色权限才可以访问)
2·创建DefaultWebSecurityManager
关联realm
自定义 realm (public class UserRealm extends AuthorizingRealm 写执行认证逻辑,执行授权逻辑)
springmvc的源码
用户请求DispatcherServlet。
DispatcherServlet调用HandlerMapping,
HandlerMapping根据请求路径找到对应的handler。
DispatcherServlet调用HandlerAdapter
HandlerAdapter去调用handler,并且在调用handler前后做一些适配。最终返回ModelAndView对象。
DispatcherServlet调用ViewResovler,拼接出完整的jsp地址。
DispatcherServlet传递模型数据给view,并且渲染打印数据给用户。
DispatcherServlet:
spring mvc的入口,整个框架运行就是在这个servlet中完成。
HandlerMapping:
处理器映射器。用于映射每个处理方法对应的请求路径。是一个map结构<url,method>。
handler:
处理器。实际上就是控制器中的每个处理方法。
HandlerAdapter:
处理器适配器。专门用来调用handler,因为在spring mvc中每个处理方法参数以及返回类型都不一样,因此需要用适配器来适配。
ViewResovler:
视图解析器。用于指定视图技术,以及视图技术相关的配置。
View:
视图。springmvc 中支持多种视图,除了jsp外 还有xml,json,pdf等。
in id方法有用到索引吗
会用到索引
list的子类
ArrayList:底层数据结构为数组,查询快,增删慢,线程不安全,效率高;
Vector:底层数据结构为数组,查询快,增删慢,线程安全,效率慢,一般不用;
LinkedList:底层数据结构为链表,查询慢,增删快,线程不安全,效率高
ArrayList
ArrayList集合继承了List的所有成员方法,没有新增,用法和List同
Vector
Vector比继承体系历史更久远,有一些实现同样获取、遍历功能更复杂的方法,老版本用,新版本基本不用。
LinkedList
LinkedList中多了新增,删除,获取First&Last元素的方法
并发包
hashMap 在线程中的并发解决办法
比如ConcurrentHashmap(锁分段技术)
容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
,Hashtable等线程安全等集合类。
synchronized来保证线程安全
对dubbo的理解
1、容器 (spring容器)
2、服务生产者
3、注册中心 (zookeeper 、redis (发布订阅 -频道))
4、服务消费者
5、监控中心(可以查看哪个方法的使用次数)
容器启动,服务生产者会把自己的服务的接口地址报告给注册中心。服务消费者订阅它需要的服务,他去查询注册中心,大哥有地址吗?有就返回服务地址。消费者拿到地址就可以去调用服务。监控中心:监控生产者和消费者的健康状况。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
注册中心挂了会产生什么影响?
对服务的调用没有任何影响,因为本地缓存了服务端的地址。
为什么使用Dubbo?
1、Dubbo提供了丰富的协议选择:Dubbo协议(服务调用),注册服务:zookeeper协议,tcp协议,http协议等。协议越底层,传输效率越高。
2、io的选择:异步的nio。
什么叫事务?简称ACID
A 事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.
C 事务的一致性(Consistency):指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.
I 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.
D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚.
线程中变量的可见性
Java中实现多线程共享变量的可见性方法有synchronize 和 volatile :
synchronize:可以用在方法或者代码块上,能保证可见性,也能保证原子性.
volatitle:用在变量上,只保证可见性,不保证原子性,不加锁,比synchronize轻量级,不会造成线程阻塞.volatitle读相当于加锁,volatitle写相当于解锁.
引用数据类型包括:
类、接口类型、数组类型、枚举类型、注解类型,字符串型。
java排序算法
冒泡,相邻元素两两比较,大的往后放,第一次完毕,最大值出现在了最大索引处。同理,其他的元素就可以排好。
简单选择排序:,把0索引的元素,和索引1以后的元素都进行比较,第一次完毕,最小值出现在了0索引。同理,其他的元素就可以排好。
插入排序:它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
快速排序:快速排序的原理就是每次设置一个基准点,这个基准点可以是要排序的一趴数之间的任何数,然后将比基准点小的数放在基准点左边,比基准点大的数放在基准点右边
二分排序:针对数组有序的情况(千万不要先排序,在查找)
10G的文件导入带数据库中怎么实现(怎么快速把10G的文件解析出来)
一、切割文件
CutText类中的方法splitFile(String filePath, String cutPath, int fileCount);
二、txt文件转换为csv文件
TxtToCSV类中的方法allFileIO(String filePath, String cutPath, int fileCount)
三、txt文件导入mysql
TxtLoadToMySQL类中的方法
toMySQL(String filePath, String cutPath, int fileCount)
微信朋友圈的点赞功能怎么实现,好友可以看到,共同好友可以看到
js == === 的区别
== 类型不一样 转换在比较
=== 类型不一样直接false 类型一样才比较
springboot 的 starter的工作原理 自动装配
@Configuration&与@Bean------>>>基于java代码的bean配置
@Conditional-------->>>>>>设置自动配置条件依赖
@EnableConfigurationProperties与@ConfigurationProperties->读取配置文件转换为bean。
@EnableAutoConfiguration、@AutoConfigurationPackage 与@Import->实现bean发现与加载。
Servlet的生命周期
加载阶段、实例化阶段、初始化阶段init、服务阶段service、销毁阶段destroy
如何取得每个部门薪资前三名的人员名称?
select e.ename, e.deptno,e.sal
from emp e
left join dept d on e.dept_id = d.id
where
(select count(*) from emp em where em.sal>=e.sal and em.deptno=e.deptno) <= 3
order by e.deptno,e.sal desc;
查询两张表中没有交集的数据
left join where id is null 的数据
swagger 注解参数
@ApiParam(name = "id", value = "用户id", required = true)
- @Api()用于类;
表示标识这个类是swagger的资源
- @ApiOperation()用于方法;
表示一个http请求的操作
- @ApiParam()用于方法,参数,字段说明;
表示对参数的添加元数据(说明或是否必填等)
- @ApiModel()用于类
表示对类进行说明,用于参数用实体类接收
- @ApiModelProperty()用于方法,字段
表示对model属性的说明或者数据操作更改
- @ApiIgnore()用于类,方法,方法参数
表示这个方法或者类被忽略
- @ApiImplicitParam() 用于方法
表示单独的请求参数
- @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam
synchronized 的方式
个人理解:
synchronized(this)
因为this是当前对象本身,所以锁定只对你自己new了并调用那个对象有用,所以另外一个人如果要new并调用,则和这个不是同一个锁,因为this变了。
synchronized(类的名.class)
每个类在jvm里面只有一个唯一的字节码,所以.class是唯一的,无论多少对象,共用此同一把锁。
接口和抽象的区别
相同点:
(1)都不能被实例化
(2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。
不同点:
(1)接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。
(2)实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
(3)接口强调特定功能的实现,而抽象类强调所属关系。
(4)接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。
(5)接口被用于常用的功能,便于日后维护和添加删除,而抽象类更倾向于充当公共类的角色,不适用于日后重新对立面的代码修改。功能需要累积时用抽象类,不需要累积时用接口。
怎么把抽象类变为接口
索引联合
mysql的事务隔离级别
1、未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
2、提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
3、可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读,但是innoDB解决了幻读
4、串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
索引的数据结构
参考博文:
www.cnblogs.com/xiaoshahai/… blog.csdn.net/u013314679/…
redis是怎么实现单线程的
spring bean 为什么没有状态
有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
Map<String, Object> map = new HashMap<String, Object>()用到了什么设计模式
工厂模式有几种写法
抽象工厂,简单(静态)工厂,多方法工厂(常用)
public class MulWayNoodlesFactory {
/**
* 模仿Executors 类
* 生产泡面
*
* @return
*/
public static INoodles createPm() {
return new PaoNoodles();
}
/**
* 模仿Executors 类
* 生产兰州拉面
*
* @return
*/
public static INoodles createLz() {
return new LzNoodles();
}
/**
* 模仿Executors 类
* 生产干扣面
*
* @return
*/
public static INoodles createGk() {
return new GankouNoodles();
}
}
INoodles lz2 = MulWayNoodlesFactory.createLz();
lz2.desc();
redis什么时候会变卡
单例模式有几种写法(五种)
懒汉式(少用),饿汉式(常用),双检锁(包含线程安全和线程不安全两种方式),静态内部类(在要明确实现 lazy loading 效果时),枚举(运用到反序列化创建对象的推荐)
红黑树是怎么保证自平衡的
任意一结点到每个叶子结点的路径都包含数量相同的黑
自平衡所需要的操作,无非是变色,左旋,右旋。变色不用多说,黑变红红变黑。
我们添加一个节点后,如果其父节点还没满三个(左右节点都为红表示满 了),并且空位在新增节点这边,那么变色即可完成修改。
如果新加节点的父节是红色,说明没空位了。那么就得拆分,将红节点变黑。这时会发现又新增了一层,于就通过父节点的左旋或右旋,将父节点上升一层。于是又变回只新增一层,又可以重新按思路走下去。
如果新增节点没有空位让其补进去,会如此一直旋转变色下去,最后到达根节点处。或是左旋或是右旋,根节点会变为原来子节点的子节点,子节点上升为根节点,到此,层数增长。由此也可以知道,层数增长总是发生在根处。
数据结构有哪些
js的选择器
IOC的实现原理
Autowired 和Resources的区别
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。 @Resources按名字,是JDK的,@Autowired按类型,是Spring的。
sprngboot文件上传用什么参数
依赖注入有几种方式
接口,构造, setter
负载均衡用了哪些算法
轮询,加强轮询,随机,加强随机,最小化原则
get方法参数为中文会变成什么
%52%
mysql怎么存储表情符号
使用 utf8mb4_general_ci(推荐) utf8mb4_unicode_ci(更准确) 字符集
进程和线程
区别:进程是分配资源的最小单位,线程是调度资源的最小单位
一个进程中有一个或多个线程
一个线程只能属于一个进程
进程之间的资源是独立的,线程之间的资源是共享的。
线程的生命周期
线程的五大状态(新建——准备——运行——阻塞——死亡)
mysql的优化方向
MYSQL优化主要分为以下四大方面:
设计:存储引擎,myisam|innodb; 字段类型,尽可能小(占用存储空间少)、尽可能定长(占用存储空间固定)、尽可能使用整数。 范式与逆范式
功能:索引,缓存,分区分表。
架构:主从复制,读写分离,负载均衡。
合理SQL:测试,经验。
过滤器Filter和拦截器Interceptor的区别
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
String 为什么不能被继承
因为 是fanal
怎么实现自动登录的
token机制,token过期之后,用refess_token 去刷新,获取新的token,保证登录状态
Springcloud和dubbo的区别
服务的发现、注册、路由、熔断、降级、分布式配置
dubbo是调用方式 rpc 通讯协议 cloud rest api
dubbo由于是二进制的传输,占用带宽会更少 cloud 带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
sync和lock的区别
- Synchronized和Lock的区别:Synchronized编码更简单,锁机制由JVM维护,在竞争不激烈的情况下性能更好。Lock功能更强大更灵活,竞争激烈时性能较好。
- 性能不一样:资源竞争激励的情况下,lock性能会比synchronize好,竞争不激励的情况下,synchronize比lock性能好,synchronize会根据锁的竞争情况,从偏向锁-->轻量级锁-->重量级锁升级,而且编程更简单。
- 锁机制不一样:synchronize是在JVM层面实现的,系统会监控锁的释放与否。lock是JDK代码实现的,需要手动释放,在finally块中释放。可以采用非阻塞的方式获取锁。
- Synchronized的编程更简洁,lock的功能更多更灵活,缺点是一定要在finally里面 unlock()资源才行。
- 用法不一样:synchronize可以用在代码块上,方法上。lock只能写在代码里,不能直接修改方法。
B+tree 的的特点
和B树的主要区别如下:
- 有 k 个子节点的非叶子节点拥有 k 个关键字,B树是k-1个。这使得非叶子节点能保存的关键字大大增加,因此树高也大大降低。
- 关键字不保存数据,只是用来索引,这样非叶子节点的所占的内存空间就变小了,读到内存中的索引信息就会更多一些,相当于减少了磁盘IO次数 数据都是存在叶子节点,这样保证了相近的数据都能存在同一块数据块里。另外也使得B+树的查询次数更稳定,每次查询次数都是相同的,需要查询到叶子节点
- 叶子节点的指针指向下一个数据对应的叶子节点,因此B+树具备了天然排序功能,在排序和范围查找的时候更方便,可以通过叶子节点的指针找到下一个叶子节点的位置
- B+树可以方便地做全表搜索,只需要从第一个叶子节点顺序往后面扫描即可,而B树则需要做树的遍历。
redis持久化机制
RDB 快照的方式写入到二进制文件中,默认的文件名为dump.rdb。 有两种触发方式 , save bgsave 全量备份
AOF 文件重写原理 增量备份
JAVA线程池有哪些配置参数,各自的作用是什么?
-
corePoolSize(核心线程数)。核心线程会一直存在,即使没有任务执行;当线程数小于核心线程数的时候,即使有空闲线程,也会一直创建线程直到达到核心线程数;allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭。 -
queueCapacity(任务队列容量)。也叫阻塞队列,当核心线程都在运行,此时再有任务进来,会进入任务队列,排队等待线程执行。 -
maxPoolSize(最大线程数),线程池里允许存在的最大线程数量;当任务队列已满,且线程数量大于等于核心线程数时,会创建新的线程执行任务;线程池里允许存在的最大线程数量。当任务队列已满,且线程数量大于等于核心线程数时,会创建新的线程执行任务。 -
keepAliveTime(线程空闲时间)。当线程空闲时间达到keepAliveTime时,线程会退出(关闭),直到线程数等于核心线程数;如果设置allowCoreThreadTimeout=true,则线程会退出直到线程数等于零。 -
allowCoreThreadTimeout(允许核心线程超时) -
rejectedExecutionHandler(任务拒绝处理器),当线程数量达到最大线程数,且任务队列已满时,会拒绝任务;调用线程池shutdown()方法后,会等待执行完线程池的任务之后,再shutdown()。如果在调用了shutdown()方法和线程池真正shutdown()之间提交任务,会拒绝新任务