1.注解用过吗?常用的注解有哪些?
前后端开发常用的注解:
控制层(Controller):
@Api (io.swagger.annotations.Api):用于生成接口文档方便开发。@Slf4j(lombok.extern.slf4j.Slf4j):用于日志输出@RestController(org.springframework.web.bind.annotation.*):相当于@Controller + @ResponseBody,作用就是返回给前端的是JSON格式的数据。
@RequestMapping(org.springframework.web.bind.annotation.*):用来处理请求映射的注解,用在类和方法上。
@Validated(org.springframework.validation.annotation.Validated):用于校验数据
@Autowired(org.springframework.web.bind.annotation.*)用于注入属性
@Resources (org.springframework.web.bind.annotation.*) 用于注入bean
@PostMapping(org.springframework.web.bind.annotation.*) 用于访问的url
@RequestBody(org.springframework.web.bind.annotation.*) 用于配置参数
服务层(Service)
@Service(org.springframework.stereotype.Service) 用于注入bean
@Autowired(org.springframework.web.bind.annotation.*)用于注入属性
@Value(org.springframework.web.bind.annotation.*) 用于注入配置文件的数据
DAO层(Mapper)
@Mapper(org.apache.ibatis.annotations.Mapper) 用于注入bean
@Param(org.apache.ibatis.annotations.Param) 用于方法的参数设置
2.消息中间件有哪些,使用的场景:
Redis:用于数据的缓存读取,分布式锁
Zookeeper:用于服务注册中心,保持服务的一致性
ElasticSearch:Elasticsearch提供了全文搜索的功能,适用于商品搜索
ElasticJob:用于定时任务的编写
Mongdb:用于图片存储
3.多线程中start与run方法的使用?
start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。 run() : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程.
4.使用多线程的场景有哪些?
Excel数据导入,批量导出、批量下载,数据文件解析入库。
5. mysql索引什么情况下失效?
(1)where 子句中使用!=或<>操作符
(2)where子句子中对字段进行null值判断
(3)where子句中使用 like '%%'
(4) in 和 not in
(5)where 子句对字段进行函数操作
6.使用explain查看索引时你一般关注那些字段?作用是什么?
id:选择标识符
作用:是SQL执行的顺序的标识,SQL从大到小的执行
select_type:表示查询的类型。
作用:表示查询中每个select子句的类型
(1) SIMPLE(简单SELECT,不使用UNIOn或子查询等)
(2) PRIMARY(子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNIOn(UNIOn中的第二个或后面的SELECT语句)
(4) DEPENDENT UNIOn(UNIOn中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNIOn RESULT(UNIOn的结果,union语句中第二个select开始后面所有select)
(6) SUBQUERY(子查询中的第一个SELECT,结果不依赖于外部查询)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,依赖于外部查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
table:输出结果集的表
作用:显示这一步所访问数据库中表名称
type:对表访问方式,表示MySQL在表中找到所需行的方式,又称“访问类型”。常用的类型有: ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)
作用:
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
possible_keys:表示查询时,可能使用的索引
作用:
指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示 null)
该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。
如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERe子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询
key:表示实际使用的索引
作用:
key列显示MySQL实际决定使用的键(索引),必然包含在possible_keys中
如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
key_len:索引字段的长度
作用:
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
不损失精确性的情况下,长度越短越好
ref:列与索引的比较
作用:列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
rows:扫描出的行数(估算的行数)
作用: 估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数
Extra:执行情况的描述和说明
作用:
该列包含MySQL解决查询的详细信息,有以下几种情况:
Using where:不用读取表中所有信息,仅通过索引就可以获取所需数据,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤
Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by
Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
Impossible where:这个值强调了where语句会导致没有符合条件的行(通过收集统计信息不可能存在结果)。
Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
No tables used:Query语句中使用from dual 或不含任何from子句
7.mysql中的锁有了解么?
mysql锁按照粒度可分为:表级锁、行级锁和页面锁三类
从类别上划分可分为:共享锁(即读锁S)和排他锁(即写锁X)
myisam默认采用表级锁,innodb默认采用行级锁
innodb的行锁主要分为三种情况:record lock,grap lock,next-key lock,(mvcc不能解决幻读问题,可在可重复读隔离级别下,使用mvcc+next-key lock来解决幻读问题)
当然还可以分为乐观锁和悲观锁,乐观锁一般通过版本号+CAS算法实现,悲观锁通过数据库的锁机制实现并对查询语句添加for update
最后讲一下死锁,死锁是指两个或两个以上进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象
8.常用的线程池有哪些?创建线程池用的是thread还是runnable?为什么要用它?线程池达到最大线程数的时候怎么处理?
(1)newSingleThreadExecutor:创建一个只有一个线程的线程池,串行执行所有任务,即使空闲时也不会被关闭。可以保证所有任务的执行顺序按照任务的提交顺序执行。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。
适用场景:需要保证顺序地执行各个任务;并且在任意时间点,不会有多个线程活动的应用场景。
(2)newFixedThreadPool:创建一个固定线程数量的线程池(corePoolSize == maximumPoolSize,使用linkedBlockingQuene作为阻塞队列)。初始化时线程数量为零,之后每次提交一个任务就创建一个线程,直到线程达到线程池的最大容量。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
适用场景:为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。
(3)newCachedThreadPool:创建一个可缓存的线程池,线程的最大数量为Integer.MAX_VALUE。空闲线程会临时缓存下来,线程会等待60s还是没有任务加入的话就会被关闭。
适用场景:适用于执行很多的短时间异步任务的小程序,或者是负载较轻的服务器。
(4)newScheduledThreadPool:创建一个支持执行延迟任务或者周期性执行任务的线程池。
Java 中创建线程池有以下两种方式:
- 通过 ThreadPoolExecutor 类创建(推荐)
- 通过 Executors 类创建
原因是:
要是因为这样的可以避免资源耗尽的风险,因为使用Executors返回线程池对象的弊端有:
(1)FixedThreadPool 和 SingleThreadPool 允许的阻塞队列长度为 Integer.MAX_VALUE,这样会导致堆积大量的请求,从而导致OOM;
(2)CachedThreadPool 允许创建的线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
所以创建线程池,最好是根据线程池的用途,然后自己创建线程池。
ThreadPoolExecutor构造函数参数的说明:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 省略...
}
(1)corePoolSize:线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列workQueue中,等待被执行;如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
(2)maximumPoolSize:线程池中允许的最大线程数。如果当前workQueue满了之后可以创建的最大线程数。
(3)keepAliveTime:空闲线程的存活时间。
(4)unit:keepAliveTime空闲线程存活时间的单位;
(5)workQueue:阻塞队列,用来存放等待被执行的任务,且任务必须实现Runnable接口,在JDK中提供了如下阻塞队列:
ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
linkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于linkedBlockingQuene
PriorityBlockingQuene:具有优先级的无界阻塞队列;
DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
linkedTransferQueue:一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
linkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
(6)threadFactory:线程工厂,主要用来创建线程,默认为正常优先级、非守护线程。
(7)handler:线程池拒绝任务时的处理策略。
执行逻辑说明:
(1)当客户端提交任务时,线程池先判断核心线程数是否小于corePoolSize,如果是,则创建新的核心线程数运行这个任务;
(2)如果正在运行的线程数大于或等于corePoolSize,则判断workQueue队列是否已满,如果未满,则将任务放入workQueue中;
(3)如果workQueue队列已经满了,则判断当前线程池中的线程数量是否大于maximumPoolSize,如果小于maximumPoolSize,则启动一个非核心线程来执行任务;
(4)如果线程池中线程数量大于或等于maximumPoolSize,那么线程池会根据设定的拒绝策略,做出相应的措施。
ThreadPoolExecutor.AbortPolic(默认):抛出RejectedExecutionException异常;
ThereadPoolExecutor.CallerRunsPolicy:在当前正在执行的线程的execute方法中运行被拒绝的任务。
ThreadPoolExecutor.DiscardOldestPoliy:丢弃workQueue中等待最长时间的任务,并将被拒绝的任务添加到队列之中。
ThreadPoolExecutor.DiscardPolicy:将直接丢弃此线程。
(5)当一个线程完成任务时,它会从workQueue中获取下一个任务来执行。
(6)当一个线程空闲超过keepAliveTime设定的时间时,线程池会判断,如果当前线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小。
9.List集合中有些员工数据,如何根据某些字段进行排序?
jdk 1.7 调用Collections的sort方法排序,需要重写Comparator的compare的方法;
jdk 1.8 调用Stream的sorted方法进行排序
10 代码中怎么开启事务?
-
Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional
11 消息中间件协议?
1.1 AMQP协议
AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。
优点:可靠、通用
1.2 MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。
优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统
1.3 STOMP协议
STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。
优点:命令模式(非topicqueue模式)
1.4 XMPP协议
XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。
优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大
1.5 其他基于TCP/IP自定义的协议
有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCPIP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。
12 jdk 1.8的新特性了解么?
1.Optional:是一个可以为null的容器对象,Optional 类的引入很好的解决空指针异常。
2.使用Lambda作为参数和返回值:如果方法的参数是一个函数式接口类型,那么就可以使用Lambda表达式进行替代
使用Lambda表达式作为方法参数,就是使用函数式接口作为方法参数
1)函数型接口: 有参数,且需要返回值。
2)供给型接口:无参数,指定返回值类型,经常用于只关注过程的代码。
3)消费型接口:不需要返回值,有参数,经常用于迭代
4)判断型接口:返回true/false,经常用于判断。
3.新的日期API——Date time
4..方法引用
方法引用符:::(双冒号)
通过对象名引用成员方法;
通过类名称引用静态方法;
通过super引用成员方法;
通过this引用成员方法。
5.新增Stream类:1)逐一处理:forEach;2)过滤:filter;3)映射:map(将stream里面的内容映射到另一个stream中)
13 版本发布用的什么?
jinkins
14 was了解么?
不了解



