java记录过程

mybatis题

什么是 Mybatis:

1、MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现。

2、MyBatis的前身是ibatis,但是在配置sql的语法上有明显的区别,并且spring目前的版本封装mybatis,至于mybatis-spring.jar文件也是mybatis团队复杂开发的jar包,用于和spring整合。之前ibatis的源码托管方是apache,而mybatis是google。

Mybaits 的优点:
1、 MyBatis把sql语句从Java源程序中独立出来, 放在单独的XML文件中编写,给程序的维护带来了很大便利。
2、MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象,大大简化了Java数据库编程的重复工作。
3、 因为MyBatis需要程序员自己去编写sql语句,程序员可以结合数据库自身的特点灵活控制sql语句, 因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。

MyBatis 框架的缺点:
1、 SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。
2、 SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

MyBatis 框架适用场合:
MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。


MyBatis 与 Hibernate 有哪些不同?
1、Hibernate:是一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过 Hibernate 提供的方法完成持久层操作。开发者并不需要熟练地掌握 SQL语句的编写,Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。然而Hibernate自身也存在着一些缺点,例如它在多表关联时,对 SQL 查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化 SQL 来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
2、MyBatis:是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,MyBatis 需要手动匹配提供 POJO、SQL和映射关系,而Hibernate只需提供POJO 和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写 SQL 要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。

#{}和${}的区别是什么?
1、#{}是预编译处理,${}是字符串替换。

2、Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的set 方法来赋值;
3、Mybatis 在处理${}时,就是把${}替换成变量的值。
4、使用#{}可以有效的防止 SQL 注入,提高系统安全性。

当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
1、可以起别名,让表字段和实体类字段保持一致。
2、可以通过resultMap来映射字段名和属性名字段一一对应。

模糊查询 like 语句该怎么写?
在字段两边加上百分号,中间放接受参数即可。整个参数需要使用单引号。

通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?
Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;
接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;
接口方法内的参数,就是传递给 sql 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符
串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中,每一个
、、、标签,都会被解析为一个
MapperStatement 对象。

举例:com.mybatis3.mappers.StudentDao.findStudentById,
可以唯一找到 namespace 为 com.mybatis3.mappers.StudentDao 下面 id 为findStudentById 的 MapperStatement。

Mapper 接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻
找策略。Mapper 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK
动态代理为 Mapper 接口生成代理对象 proxy,代理对象会拦截接口方法,转而执行 MapperStatement 所代表的 sql,然后将 sql 执行结果返回。

ZooKeeper面试题

ZooKeeper 提供了什么?

文件系统、通知机制

Zookeeper 文件系统?

Zookeeper 提供一个多层级的节点命名空间(节点称为 znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。
Zookeeper 为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得 Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限为1M。

ZAB 协议?

ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。
ZAB 协议包括两种基本的模式:崩溃恢复和消息广播。
当整个 zookeeper 集群刚刚启动或者 Leader 服务器宕机、重启或者网络故障导致不存在过半的服务器与 Leader 服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的 Leader 服务器,然后集群中 Follower 服务器开始与新的 Leader 服务器进行数据同步,当集群中超过半数机器与该 Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader 服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。 

什么是Zookeeper 注册中心?

什么是注册中心,顾名思义,就是让众多的服务,都在Zookeeper中进行注册,啥是注册,注册就是把自己的一些服务信息,比如IP,端口,还有一些更加具体的服务信息,都写到 Zookeeper节点上, 这样有需要的服务就可以直接从zookeeper上面去拿,怎么拿呢? 这时我们可以定义统一的名称,比如,User-Service, 那所有的用户服务在启动的时候,都在User-Service 这个节点下面创建一个子节点(临时节点),这个子节点保持唯一就好,代表了每个服务实例的唯一标识,有依赖用户服务的比如Order-Service 就可以通过User-Service 这个父节点,就能获取所有的User-Service 子节点,并且获取所有的子节点信息(IP,端口等信息),拿到子节点的数据后Order-Service可以对其进行缓存,然后实现一个客户端的负载均衡,同时还可以对这个User-Service 目录进行监听, 这样有新的节点加入,或者退出,Order-Service都能收到通知,这样Order-Service重新获取所有子节点,且进行数据更新。这个用户服务的子节点的类型为临时节点。 第一节课有讲过,Zookeeper中临时节点生命周期是和SESSION绑定的,如果SESSION超时了,对应的节点会被删除,被删除时,Zookeeper 会通知对该节点父节点进行监听的客户端, 这样对应的客户端又可以刷新本地缓存了。当有新服务加入时,同样也会通知对应的客户端,刷新本地缓存,要达到这个目标需要客户端重复的注册对父节点的监听。这样就实现了服务的自动注册和自动退出。
 

四种类型的数据节点 Znode

1、PERSISTENT-持久节点
除非手动删除,否则节点一直存在于 Zookeeper 上 
2、EPHEMERAL-临时节点
临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper 连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除。 
3、PERSISTENT_SEQUENTIAL-持久顺序节点
基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。 
4、EPHEMERAL_SEQUENTIAL-临时顺序节点
基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字

Zookeeper Watcher 机制 -- 数据变更通知

Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。 
工作机制: 
1.客户端注册 watcher
2.服务端处理 watcher
3.客户端回调 watcher 
Watcher 特性总结:
1、一次性
无论是服务端还是客户端,一旦一个 Watcher 被触发,Zookeeper 都会将其从相应的存储中移除。这样的设计有效的减轻了服务端的压力,不然对于更新非常频繁的节点,服务端会不断的向客户端发送事件通知,无论对于网络还是服务端的压力都非常大。
2、客户端串行执行
客户端 Watcher 回调的过程是一个串行同步的过程。
3、轻量 
3.1、Watcher 通知非常简单,只会告诉客户端发生了事件,而不会说明事件的具体内容。
3.2、客户端向服务端注册 Watcher 的时候,并不会把客户端真实的 Watcher 对象实体传递到服务端,仅仅是在客户端请求中使用 boolean 类型属性进行了标记。
4、watcher event 异步发送 watcher 的通知事件从 server 发送到 client 是异步的,这就存在一个问题,不同的客户端和服务器之间通过 socket 进行通信,由于网络延迟或其他因素导致客户端在不通的时刻监听到事件,由于 Zookeeper 本身提供了 ordering guarantee,即客户端监听事件后,才会感知它所监视 znode发生了变化。所以我们使用 Zookeeper 不能期望能够监控到节点每次的变化。Zookeeper 只能保证最终的一致性,而无法保证强一致性。
5、注册 watcher getData、exists、getChildren
6、触发 watcher create、delete、setData
7、当一个客户端连接到一个新的服务器上时,watch 将会被以任意会话事件触发。当与一个服务器失去连接的时候,是无法接收到 watch 的。而当 client 重新连接时,如果需要的话,所有先前注册过的 watch,都会被重新注册。通常这是完全透明的。只有在一个特殊情况下,watch 可能会丢失:对于一个未创建的 znode的 exist watch,如果在客户端断开连接期间被创建了,并且随后在客户端连接上之前又删除了,这种情况下,这个 watch 事件可能会被丢失。 

客户端注册 Watcher 实现

1.调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象
2.标记请求 request,封装 Watcher 到 WatchRegistration
3.封装成 Packet 对象,发服务端发送 request
4.收到服务端响应后,将 Watcher 注册到 ZKWatcherManager 中进行管理
5.请求返回,完成注册。

服务端处理 Watcher 实现

1、服务端接收 Watcher 并存储
接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节点的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端的连接,实现了 Watcher 的 process 接口,此时可以看成一个 Watcher 对象)存储在WatcherManager 的 WatchTable 和 watch2Paths 中去。
2、Watcher 触发
以服务端接收到 setData() 事务请求触发 NodeDataChanged 事件为例: 
2.1 封装 WatchedEvent 
将通知状态(SyncConnected)、事件类型(NodeDataChanged)以及节点路径封装成一个 WatchedEvent 对象 
2.2 查询 Watcher
从 WatchTable 中根据节点路径查找 Watcher 
2.3 没找到;说明没有客户端在该数据节点上注册过 Watcher 
2.4 找到;提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher(从这里可以看出 Watcher 在服务端是一次性的,触发一次就失效了) 
3、调用 process 方法来触发 Watcher
这里 process 主要就是通过 ServerCnxn 对应的 TCP 连接发送 Watcher 事件通知。 

客户端回调 Watcher

客户端 SendThread 线程接收事件通知,交由 EventThread 线程回调 Watcher。
客户端的 Watcher 机制同样是一次性的,一旦被触发后,该 Watcher 就失效了。

Dubbo 面试题

为什么要用 Dubbo?

1、Dubbo一款优秀的分布式服务框架

2、Dubbo提供高性能的RPC服务

3、Dubbo具有注册中心、监控中心。

Dubbo 的整体架构设计有哪些分层?

框架设计共划分了10层,最上面的Service层是留给实际使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层。图中左边为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。

接口服务层(Service):该层与业务逻辑相关,根据provider和consumer的业务设计对应的接口和实现

配置层(Config):对外配置接口,以ServiceConfig和ReferenceConfig为中心

服务代理层(Proxy):服务接口透明代理,生成服务的客户端Stub和服务端的Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory

服务注册层(Registry):封装服务地址的注册和发现,以服务URL为中心,扩展接口为RegistryFactory、Registry、RegistryService

路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router和LoadBlancce

监控层(Monitor):RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor和MonitorService

远程调用层(Protocal):封装RPC调用,以Invocation和Result为中心,扩展接口为Protocal、Invoker和Exporter

信息交换层(Exchange):封装请求响应模式,同步转异步。以Request和Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer

网络传输层(Transport):抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec

数据序列化层(Serialize):可复用的一些工具,扩展接口为Serialization、ObjectInput、ObjectOutput和ThreadPool

Dubbo默认使用的是什么通信框架,还有别的选择吗?

Dubbo 默认使用 Netty 框架,也是推荐的选择,另外内容还集成有Mina、Grizzly

Dubbo服务调用是阻塞的吗?

默认是同步等待结果阻塞的,支持异步调用。Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个 远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。

Dubbo一般使用什么注册中心?还有别的选择吗?

推荐使用 Zookeeper 作为注册中心,还有 Redis、Multicast、Simple 注册中心,但不推荐。

Dubbo默认使用什么序列化框架,你知道的还有哪些?

推荐使用 Hessian 序列化,还有 Duddo、FastJson、Java 自带序列化。

Dubbo服务提供者能实现失效踢出是什么原理?

服务失效踢出基于 Zookeeper 的临时节点原理。

Redis 的持久化机制是什么?各自的优缺点?

1、RDBRedis DataBase)持久化方式: 是指用数据集快照的方式半持久化模式)

记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化

结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

优点:

1、只有一个文件 dump.rdb,方便持久化。

2、容灾性好,一个文件可以保存到安全的磁盘。

3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO

最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis

的高性能) 4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:

1、数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生

故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)

2、AOFAppend-only file)持久化方式: 是指所有的命令行记录以 redis 命令请

求协议的格式完全持久化存储)保存为 aof 文件。

优点:

1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次

命令操作就记录到 aof 文件中一次。

2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof

工具解决数据一致性问题。

3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令

进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

缺点:

1、AOF 文件比 RDB 文件大,且恢复速度慢。

2、数据集大的时候,比 rdb 启动效率低。

MySQL 面试题

MySQL 中有哪几种锁?

基于锁的属性分类:共享锁(读锁)、排他锁(写锁)
基于锁的粒度分类:行级锁((innodb )、表级锁( innodb、myisam)、页级锁( innodb引擎)、记录锁、间隙锁、临键锁

MySQL 中有哪些不同的表格?

分别是:BDB、InnoBDB、HEAP、ISAM、MERGE、MYISAM、Gemeni。

简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别

1. InnoDB 支持事务,MyISAM 不支持事务。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一

个事务,这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一。

2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败。

3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,

先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指

针。主键索引和辅助索引是独立的。(也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节

点都是数据文件的地址指针。)

4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快

(注意不能加有任何WHERE条件)。

5. InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从

MyISAM 变成 InnoDB 的重要原因之一。

6. Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了。

7. MyISAM表格可以被压缩后进行查询操作。

8. InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有

9. Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI

  Innodb:frm是表定义文件,ibd是数据文件

  Myisam:frm是表定义文件,myd是数据文件,myi是索引文件

如何选择使用InnoDB与MyISAM

1. 是否要支持事务,如果要请选择 InnoDB,如果不需要可以考虑 MyISAM。

2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用InnoDB。

3. 系统奔溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB。

4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的。如果你不知道用什么存储引擎,那就用InnoDB,至少不会差。

MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

read uncommited :读到未提交数据
read committed:脏读,不可重复读
repeatable read:可重读
serializable :串行事物

CHAR 和 VARCHAR 的区别?

1.char类型的长度是固定的,varchar的长度是可变的。

这就表示,存储字符串'abc',使用char(10),表示存储的字符将占10个字节(包括7个空字符)

使用varchar(10),则表示只占3个字节,10是最大值,当存储的字符小于10时,按照实际的长度存储。

2.char类型的效率比varchar的效率稍高

3.varchar与varchar的区别

varchar是oracle开发的一个数据类型。

工业标准的varchar可以存储空字符串,oracle的varchar还可以存储NULL值,如果想要有向后兼容的能力建议使用varchar

4.varchar比char节省空间,但是在效率上比char稍差些。既要获得效率即必须牺牲一点空间,这就是设计上的""以空间换时间""

varchar虽然比char节省空间,但是一个varchar列经常被修改,而且每次修改的数据长度不同,这会引起“行迁移的现象”,

而这造成的多余的I/O,是数据库设计中尽量避免的,在这种情况下使用char代替varchar会更好些。

主键和候选键有什么区别?

表格的每一行都由主键唯一标识,一个表只有一个主键。主键也是候选键。按照惯例,候选键可以被指定为主键,并且可以用于任何外键引用。

myisamchk 是用来做什么的?

它用来压缩 MyISAM 表,这减少了磁盘或内存使用。

如果一个表有一列定义为 TIMESTAMP,将发生什么?

每当行被更改时,时间戳字段将获取当前时间戳。

列设置为 AUTO INCREMENT 时,如果在表中达到最大值,会发生什么情况?

它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。

怎样才能找出最后一次插入时分配了哪个自动增量?

LAST_INSERT_ID 将返回由 Auto_increment 分配的最后一个值,并且不需要指定表名称。

你怎么看到为表格定义的所有索引?

通过以下方式定义的

SHOW INDEX FROM tablename;

Java 并发编程

在 java 中守护线程和本地线程区别?

java中的线程分为两种:守护线程(Daemon)和用户线程(User)。

任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。

两者的区别:

唯一的区别是判断虚拟机(JVM)何时离开,Daemon是为其他线程提供服务,如果全部的User Thread已经撤离,Daemon 没有可服务的线程,JVM撤离。也可以理解为守护线程是JVM自动创建的线程(但不一定),用户线程是程序创建的线程;比如JVM的垃圾回收线程是一个守护线程,当所有线程已经撤离,不再产生垃圾,守护线程自然就没事可干了,当垃圾回收线程是Java虚拟机上仅剩的线程时,Java虚拟机会自动离开。

扩展:Thread Dump打印出来的线程信息,含有daemon字样的线程即为守护进程,可能会有:服务守护进程、编译守护进程、windows下的监听Ctrl+break的守护进程、Finalizer守护进程、引用处理守护进程、GC守护进程。

线程与进程的区别?

进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元。

一个程序至少有一个进程,一个进程至少有一个线程。

什么是多线程中的上下文切换?

在上下文切换过程中,CPU 会停止处理当前运行的程序,并保存当前程序运行的 

具体位置以便之后继续运行。从这个角度来看,上下文切换有点像我们同时阅读 

几本书,在来回切换书本的同时我们需要记住每本书当前读到的页码。在程序中,

上下文切换过程中的“页码”信息是保存在进程控制块(PCB)中的。PCB 还经 

常被称作“切换桢”(switchframe)。“页码”信息会一直保存到 CPU 的内存 

中,直到他们被再次使用。

上下文切换是存储和恢复 CPU 状态的过程,它使得线程执行能够从中断点恢复执 

行。上下文切换是多任务操作系统和多线程环境的基本特征。

死锁与活锁的区别,死锁与饥饿的区别?

死锁,是指两个或两个以上的进程(或线程)执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用干预,他们都死等下去,也都将无法往下推进。

产生死锁的必要条件:

1、互斥条件:所谓互斥即线程在某一时间内独占资源。

2、请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源持有不放。

3、不剥夺条件:线程已获得的资源,在未使用结束前,不能强行剥夺。

4、循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

典型案例:哲学家共进午餐问题。

2、什么是活锁
线程没有被阻塞,但由于某些条件未能满足,导致一直重复尝试->失败,尝试->失败,如此下去。

3、什么是饥饿
一个或者多个线程,因为种种原因无法获得所需要的资源,导致一直无法执行的状态。

java 中导致饥饿的原因:

1、高优先级线程吞噬所有的低优先级线程的  CPU 时间。

2、线程被永久堵塞在等待进入同步块的状态,因其他线程总是能在它之前持续地对该同步块进行 访问。

3、线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的 wait方法),因为其他线程总是被持续地获得唤醒。

3、活锁和死锁的区别
1)处于活锁的实体是在不断的改变状态,所谓的“活”; 处于死锁的实体表现为等待。

2)活锁可能自行解开,死锁不能自行解开。

Java 中用到的线程调度算法是什么?

有两种调度模型:分时调度模型和抢占式(java默认使用)调度模型。

  • 分时调度模型: 平均分配每个线程占用的 CPU 的时间片。
  • 抢占式调度模型: 让优先级高的线程占用CPU,如果线程优先级相同,那么就随机选择一个线程。

什么是线程组,为什么在 Java 中不推荐使用?

  1. 线程组ThreadGroup对象中的stop,resume,suspend会导致安全问题,主要是死锁问题,已经被官方废弃。
  2. 线程组ThreadGroup不是线程安全的,在使用过程中不能及时获取安全的信息。

基于上述原因,推荐使用线程池。

并发编三要素?

1.原子性:一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行

2.可见性:多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他 线程可以立即看到修改的结果

3.有序性:程序的执行顺序按照代码的先后顺序来执行

如何解决原子性?

1通过使用局部变量,局部变量存储于栈中,线程私有,不存在变量共享,就不存在线程之间的影响。

2加锁,使用synchronized 或者 lock

使用synchronized,有synchronized修饰方法,synchronized(lock),synchronized(Xxx.class)

lock和synchronized区别:一个是手动挡一个是自动档。手动挡的自由度更大,lock可以有更多的操作。lock.lock()一直等待到拿的到锁,lock.tryLock()拿不到值会直接返回false,拿得到返回true

如何解决可见性?

禁用缓存,使用volatile关键字。为了提高CPU的处理速度,CPU一般不直接跟内存进行通信,而是将数据读到内部缓存,被volatile修饰的变量一旦发生了修改,CPU嗅探在总线上传播的数据来检查自己的缓存是否失效,会使得自身工作内存失效掉,从而去主内存重新获取新值。

如何解决有序性?

为了提高CPU的处理速度,一般会对指令进行重排序。volatile还可以确保指令重排序时,内存屏障前后的指定不会互串。

多线程的价值?

1、发挥多核 CPU 的优势 

多线程,可以真正发挥出多核 CPU 的优势来,达到充分利用 CPU 的目的,采用多 

线程的方式去同时完成几件事情而不互相干扰。

2、防止阻塞 

从程序运行效率的角度来看,单核 CPU 不但不会发挥出多线程的优势,反而会因 

为在单核 CPU 上运行多线程导致线程上下文的切换,而降低程序整体的效率。但 

是单核 CPU 我们还是要应用多线程,就是为了防止阻塞。试想,如果单核 CPU 使 

用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未 

返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。

多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数 

据阻塞,也不会影响其它任务的执行。

3、便于建模 

这是另外一个没有这么明显的优点了。假设有一个大的任务 A,单线程编程,那么 

就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务 A 分解成 

几个小任务,任务 B、任务 C、任务 D,分别建立程序模型,并通过多线程分别运 

行这几个任务,那就简单很多了。

创建线程的有哪些方式?

方式一:继承Thread类,覆写run方法,创建实例对象,调用该对象的start方法启动线程。

方式二:创建Runnable接口的实现类,类中覆写run方法,再将实例作为此参数传递给Thread类有参构       造创建线程对象,调用start方法启动。

方式三:创建Callable接口的实现类,类中覆写call方法,创建实例对象,将其作为参数传递给

FutureTask类有参构造创建FutureTask对象,再将FutureTask对象传递给Thread类的有参构造创建线程对象,调用start方法启动。

区别:

方式一有单继承的局限性。

方式二和方式三避免了单继承的局限,使用更广泛。而方式二适用于无需返回值的场景,方式三使用于  有返回值的场景。

创建线程的三种方式的对比?

1、采用实现 Runnable、Callable 接口的方式创建多线程。
优势是:
线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
在这种方式下,多个线程可以共享同一个 target 对象,所以非常适合多个相同线
程来处理同一份资源的情况,从而可以将 CPU、代码和数据分开,形成清晰的模
型,较好地体现了面向对象的思想。
劣势是:
编程稍微复杂,如果要访问当前线程,则必须使用 Thread.currentThread()方法。
2、使用继承 Thread 类的方式创建多线程
优势是:
编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread()方法,
直接使用 this 即可获得当前线程。
劣势是:
线程类已经继承了 Thread 类,所以不能再继承其他父类。
3、Runnable 和 Callable 的区别
1、Callable 规定(重写)的方法是 call(),Runnable 规定(重写)的方法是 run()。
2、Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的。
3、Call 方法可以抛出异常,run 方法不可以。
4、运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。它提供
了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过 Future
对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
 

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

通过Executors工厂方法创建
通过new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)自定义创建
 

Java 面试题

面向对象的特征有哪些方面?

面向对象的特征是:1、“抽象”,把现实世界中的某一类东西,提取出来,用程序代码表示;2、“封装”,把过程和数据包围起来,对数据的访问只能通过已定义的界面;3、“继承”,一种联结类的层次模型;4、“多态”,允许不同类的对象对同一消息做出响应。

访问修饰符 public,private,protected,以及不写(默认)时的区别?

区别如下:
作用域        当前类        同包        子类             其他
public         √                 √                 √                √
protected   √                 √                 √                 ×
default       √                 √                 ×                 ×
private       √                 ×                 ×                 ×
类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。
 

String 是最基本的数据类型吗?

答:不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型和枚举类型,剩下的都是引用类型。String 类是final类,不可以被继承。

float f=3.4;是否正确?

没错,但是f的值不是3.4 是3.4000000000001,3.4加个f才能表示是float型,明面数字都是int型的

short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

第一题:short s1 = 1; s1 = s1 + 1;

错! s1 + 1,s1是short类型,1是int型,s1会自动转换为int型的1,与1相加后,得到int型的2,要向左侧的short类型的s1看齐,即需要通过强制类型转换。正确写法:s1 = (short) (s1 + 1);

第二题:short s1 = 1; s1 += 1;

正确! 执行s1+=1;其实执行的是s1 = (short) (s1 + 1); 其中会有一个强制转换的过程。

第三题:short s1=1,s2=1;short s3=s1+s2;

错误!这里是编译器从数据安全方面考虑,如果s1和s2都是较大的short类型数,可能会导致溢出,所以会要求强制转换到int。正确写法:short s3 = (int)s1 + s2;

Java 有没有 goto?

goto 是Java中的保留字,在目前版本的Java中没有使用

int 和 Integer 有什么区别?

Integer是int的包装类;int是基本数据类型。
Integer变量必须实例化后才能使用;int变量不需要。
Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值。
Integer的默认值是null;int的默认值是0
 

&和&&的区别?

&&是逻辑操作符,而&是位操作

Java 面试题

Java 中能创建 volatile 数组吗?

能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不 

是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,

但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护 

作用了。

volatile 能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。
以上是网络上搜索到的答案。
我觉得是 不能把非源子操作改成源子操作,毕竟存在i++这种操作,而且从本质上来讲 ,volatile只能保证内存可见性,而不是保证原子性,原理可参考https://blog.csdn.net/T_luyang_T/article/details/103188314。
而且原子性和可见性的含义都是不一样的 ,这个问题从问法上就是有问题。

可见性:一个线程对共享变量的修改,更够及时的被其他线程看到
原子性:即不可再分了,不能分为多步操作。比如赋值或者return。比如"a = 1;"和 "return a;"这样的操作都具有原子性。类似"a += b"这样的操作不具有原子性,在某些JVM中"a += b"可能要经过这样三个步骤:
① 取出a和b
② 计算a+b
③ 将计算结果写入内存

但是Synchronize是可以保证可见性和原子性

volatile 修饰符的有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。

double 和 long 都是 64 位宽,因此对这两种类型的读是分为两部分的,第一次 

读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 

volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个 

作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的 

说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(write

barrier),读一个 volatile 变量之前,会插入一个读屏障(read barrier)。意 

思就是说,在你写一个 volatile 域时,能保证任何线程都能看到你写的值,同时,

在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其 

他所有写的值更新到缓存。

10 个线程和 2 个线程的同步代码,哪个更容易写?

从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互 

独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的 

竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。

你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

面试官:你是如何调用 wait()方法的?使用 if 块还是循环?为什么?_枫哥和java的博客-CSDN博客

什么是线程局部变量?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

我们能创建一个包含可变对象的不可变对象吗?

是的,我们是可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,

不要共享可变对象的引用就可以了,如果需要变化时,就返回原对象的一个拷贝。

最常见的例子就是对象中包含一个日期对象的引用。

我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于byte 类型的范围,将会出现什么现象?

我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化, int 类型
的高 24 位将会被丢弃,因为 byte 类型的范围是从 -128 到 127
 

存在两个类,B 继承 A,C 继承 B,我们能将 B 转换为 C 么?

如 C = (C) B;

不可以,强转会报错,如果new对象强转的话编译不会报错。但是强转会报错。

Java 中 ++ 操作符是线程安全的吗?

不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。

a = a + b 与 a += b 的区别

一、性能方面
  a=a+b是加法运算 需要两次寻找地址而a+=b是增量运算有寄存器优先时 只有一次地址查找。效率方面后者略高于前者 基于现在计算机的发展可忽略不计。

二、可读性方面
  两者都是赋值运算,一般情况下可以认为两者没有什么区别 但前者与数学算法描述更接近相对来说更严谨而后者书写更快捷但可读性下降。

三、数据类型方面
  两者写法上主要在于是否能进行数据类型自动转换,事实上就是类型与精度上的差异。eg:当两个操作数 数据类型一致时两种形式的运算结果没有差别 但数据类型不同时 且a值的数据类型精度低时 此时两种形式就有区别了。(类型不一样直接加会报错,+=的话会自动转换类型)

我能在不进行强制转换的情况下将一个 double 值赋值给 long类型的变量吗?

不可以直接赋值,只能进行转换,但是如果doubl有小数点的话精度会丢失

3*0.1 == 0.3 将会返回什么?true 还是 false?

返回false 因为有些浮点数不能完全精确的表示出来。

int 和 Integer 哪个会占用更多的内存?

int 和Integer所占内存比较:. Integer对象会占用更多的内存。. Integer是一个对象,需要存储对象的元数据。. 但是int是一个原始类型的数据,所以占用的空间更少。.

为什么 Java 中的 String 是不可变的

Java 中的 String 不可变是因为 Java 的设计者认为字符串使用非常频繁,将字 

符串设置为不可变可以允许多个客户端之间共享相同的字符串。

前者设计成了不可修改, 后者加了final。

64 位 JVM 中,int 的长度是多数?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。

32位JVM和64位JVM的最大堆内存分别是多数?

理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5 GB,Solaris 大约 3GB。64 位 JVM允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

JRE、JDK、JVM 及 JIT 之间有什么不同?

JRE、JDK、JVM 及 JIT 之间有什么不同?
JRE 代表 Java 运行时(Java run-time),是运行 Java 引用所必须的。JDK 代
表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java
编译器,它也包含 JRE。JVM 代表 Java 虚拟机(Java virtual machine),它
的责任是运行 Java 应用。JIT 代表即时编译(Just In Time compilation),当
代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主
要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。
 

解释 Java 堆空间及 GC?

当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于 

创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内 

部的一个进程,回收无效对象的内存用于将来的分配。

你能保证 GC 执行吗?

不能,虽然你可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC

的执行。

怎么获取 Java 程序使用的内存?堆使用的百分比?

可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。
通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。
Runtime.freeMemory() 方法返回剩余空间的字节数
Runtime.totalMemory() 方法总内存的字节数
Runtime.maxMemory() 返回最大内存的字节数
 

Java 中堆和栈有什么区别?

https://www.jb51.net/article/188857.htm

final、finalize 和 finally 的不同之处?

final,finally,finalize三者的含义和区别 - 知乎

List、Set、Map 和 Queue 之间的区别(答案)

List 是一个有序集合,允许元素重复。它的某些实现可以提供基于下标值的常量访问时间,但是这不是 List 接口保证的。Set 是一个无序集合。Map是一个键值对,Queue模拟的是一个队列,先进先出。使用queue.poll()可以读取集合里面的值,读取完以后再次读取就是空的。

Queue的poll() 方法和 remove() 方法的区别?

poll用来删除头部元素,并返回删除的元素的值,如果数组里面没有值了他将返回null,remove() 方法用来删除头部或者指定元素。如果数组里面没有值的话就会抛出异常。

Java 中 LinkedHashMap 和 PriorityQueue 的区别是什么?

PriorityQueue 保证最高或者最低优先级的的元素总是在队列头部,但是LinkedHashMap 维持的顺序是元素插入的顺序。当遍历一个 PriorityQueue时,没有任何顺序保证,但是 LinkedHashMap 课保证遍历顺序是元素插入的顺序。

ArrayList 与 LinkedList 的不区别?

1.底层存储不同
      ArrayList底层采用数组存储
      LinkedList底层采用双向链表存储
     
    2。访问方式不同
      ArrayList使用下标访问,速度非常快
      LinkedList无法使用随机访问,所以查询速度不快
    
    3.效率不同
      ArrayList的时间复杂度为 O(1)
      LinkedList的时间复杂度为 O(n)
 

用哪两种方式来实现集合的排序?

你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。

Java 中的 LinkedList 是单向链表还是双向链表?

双向链表

Java 中的 TreeMap 是采用什么树实现的

Java 中的 TreeMap 是使用红黑树实现的。

Hashtable 与 HashMap 有什么不同之处?

1、hash值不同

HashTable:直接使用对象的hashCode

HashMap:重新计算hash值

2、两个遍历方式的内部实现不同

Hashtable、HashMap两者都是使用了Iterator,但是,因为一些历史原因,Hashtable除了使用了Iterator之外,还使用了Enumeration。

3、是否提供contains方法

Hashtable:Hashtable和HashMap不同,它保留了contains、containsValue以及containsKey3个方法

HashMap:它去掉了Hashtable的contains方法,改为了containsKey和containsValue

4、内部实现使用的数组初始化和扩容方式不同

HashTable:在不指定容量的情况下的默认容量为11;不要求底层数组的容量一定要为2的整数次幂;扩容时将容量变为原来的2倍加1。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

HashMap:在不指定容量的情况下的默认容量为16;要求一定为2的整数次幂;扩容时,将容量变为原来的2倍

HashTable中hash数组默认大小是11,增加的方式是old*2+1

5、key和value是否允许null值

Hashtable:key和value都不允许出现null值

HashMap:null能够作为键,这样的键只有一个,能够有一个或者是多个键所对应的值为null

6、线程安全性不同

Hashtable:Synchronize;在多线程并发的情况下,能够直接使用Hashtable,不要自己为它的方法实现同步

HashMap:在缺省情况下是非Synchronize的;使用HashMap的时候就需要自己增加同步处理;HashMap是线程不安全的

7、继承的父类不同

Hashtable:继承Dictionary类

HashMap:继承AbstractMap类

Java 中的 HashSet,内部是如何工作的?

HashSet 的内部采用 HashMap来实现。由于 Map 需要 key 和 value,所以HashSet中所有 key 的都有一个默认 value。

类似于HashMap,HashSet 不允许重复的 key,只允许有一个null key,意思就是 HashSet 中只允许存储一个 null 对象。

ArrayList 和 HashMap 的默认大小是多数?

ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)

有没有可能两个不相等的对象有有相同的 hashcode?

有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。相等 hashcode 值的规定只是说如果两个对象相等,必须有相同的 hashcode 值,但是没有关于不相等对象的任何规定。

两个相同的对象会有不同的的 hashCode 吗?

个人觉得不会

我们可以在 hashcode() 中使用随机数字吗?

不行,因为对象的 hashcode 值必须是相同的。

Java 中,Comparator 与 Comparable 有什么不同?

1.Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户
定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义
对象的顺序。

2.Comparable 接口用于实体类的内部排序,在实体类中直接继承Comparable接口,接口中只有一个comparaTo(Object obj)方法,重写comparaTo(Object obj)方法即可完成排序,该方法只需要传入一个参数(实体类对象)即可,返回值为int。

3.Comparator接口用于实体类的外部排序,需要另外创建一个类实现Comparator接口,接口中在1.8之后新增了多个方法,可以只重写compara(Object obj1,Object obj2)方法,返回值也为int。接口中有equals()方法也建议在比较时进行重写,防止出现对象比较时会调用Object.equals()方法,比较两个对象的引用地址。

Java 中怎么创建 ByteBuffer?

可以使用new一个

Java 采用的是大端还是小端?

大端 “java 全部为大端(与平台无关)

ByteBuffer 中的字节序是什么?

字节序分为两种:BIG-ENDIAN—-大字节序、LITTLE-ENDIAN—-小字节序

TCP 协议与 UDP 协议有什么区别?

1.最大的区别就是TCP是面向连接的,而UDP是无连接的
2.TCP是可靠的,安全的;UDP是不可靠的,不安全的,但是传输数据的速率快
3.TCP比UDP更复杂,它具有流量控制和拥塞控制机制
4.TCP面向字节流;UDP是面向报文的
5.TCP对系统资源要求较多,UDP对系统资源要求较少。TCP首部有20个字节,UDP的首部只有8个字节的首部开销。
6.TCP连接只能是一对一的;而UDP支持一对一,一对多和多对多的交互通信
7.UDP协议不使用确认信息对报文的到达进行确认,它不能保证报文到达的顺序,也不能向源端反馈信息来进行流量控制,因而会出现报文丢失等现象。
8.TCP肯定将数据传送出去,并且在目的主机上的应用程序能以正确的顺序接收数据。

Java中的String、StringBuilder和StringBuffer三者的区别

在这方面运行速度从快到慢为:StringBuilder > StringBuffer > String
String最慢是因为String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。

线程安全
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

总结
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
也就说一般情况下需要append字符串到字符串,用StringBuilder

Java 中,编写多线程程序的时候你会遵循哪些最佳实践?

a)给线程命名,这样可以帮助调试。

b)最小化同步的范围,而不是将整个方法同步,只对关键部分做同步。

c)如果可以,更偏向于使用 volatile 而不是 synchronized。

d)使用更高层次的并发工具,而不是使用 wait() 和 notify() 来实现线程间通 

信,如 BlockingQueue,CountDownLatch 及 Semeaphore。

e)优先使用并发集合,而不是对集合进行同步。并发集合提供更好的可扩展性。

列出 5 个应该遵循的 JDBC 最佳实践

1、使用批量处理来更新和新增数据。

2、使用preparedStatement来避免SQL语句异常,并提高性能。

3、使用数据库连接池。

4、通过列名来获取结果集,不要使用下标来获取。

说出几条 Java 中方法重载的最佳实践?

a)不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参 

数。

b)不要重载参数数量一致,而只是参数顺序不同的方法。

c)如果重载的方法参数个数多于 5 个,采用可变参数。

在多线程环境下,SimpleDateFormat 是线程安全的吗?

不是,非常不幸,DateFormat 的所有实现,包括 SimpleDateFormat 都不是 

线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中 

使用,如 将 SimpleDateFormat 限制在 ThreadLocal 中。如果你不这么做,

在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、

时间处理的所有实践来说,我强力推荐 joda-time 库。

Java 中,怎么在格式化的日期中显示时区?

在格式化后面加上Z,表示的就是时区!

Java 中 java.util.Date 与 java.sql.Date 有什么区别?

  • java.util.Date : 通常情况下用它获取当前时间或构造时间
  • java.sql.Date : 是针对SQL语句使用的,它只包含日期而没有时间部分

继承关系:java.lang.Object --》 java.util.Date --》 java.sql.Date

怎么检查一个字符串只包含数字?解决方案

1、可以使用正则判断。

2、使用自带方法

3、使用ascii码

在不使用 StringBuffer 的前提下,怎么反转一个字符串?

String.valueOf(XXX) 或者直接使用强转

在没有使用临时变量的情况如何交换两个整数变量的值?

使用加减法或者乘除法交换

接口是什么?为什么要使用接口而不是直接使用具体类?

接口用于定义 API。它定义了类必须得遵循的规则。同时,它提供了一种抽象,因为客户端只使用接口,这样可以有多重实现,如 List 接口,你可以使用可随机访问的 ArrayList,也可以使用方便插入和删除的 LinkedList。接口中不允许写代码,以此来保证抽象,但是 Java 8 中你可以在接口声明静态的默认方法,这种方法是具体的。

Java 中,抽象类与接口之间有什么不同?

1、抽象类中可以包含普通方法,但接口中只能包含public与abstract方法(JDK 1.8之前);

2、抽象类中的成员变量没有访问权限的限制,但接口中的变量只能被public static final修饰;

3、一个接口可以继承多个接口,但一个类只能有一个父类,类可以实现多个接口;

4、抽象类是对一类事物的抽象,接口则是对行为的抽象。一个类继承一个抽象类代表“是不是”的关系,而一个类实现一个接口则表示“有没有”的关系。

java常用的设计模式有哪些

​​​​​​​Java中常见的设计模式_熊先森的宝的博客-CSDN博客_java常用设计模式

适配器模式是什么?什么时候使用?

适配器模式(adapter pattern)是将一个类的接口转换成期待的类型,主要目的为兼容性,一个适配使得因接口不兼容而不能在一起工作的类能在一起工作,做法是将类自己的接口包裹在一个已存在的类中,它的别名为包装器,属于结构性模式。

什么是“依赖注入”和“控制反转”?为什么有人使用?

​​​​​​​控制反转(IOC)是 Spring 框架的核心思想,用我自己的话说,就是你要做一件

事,别自己可劲 new 了,你就说你要干啥,然后外包出去就好

依赖注入(DI) 在我浅薄的想法中,就是通过接口的引用和构造方法的表达,将

一些事情整好了反过来传给需要用到的地方

  • 控制反转是一种思想
  • 依赖注入是一种设计模式

依赖注入有什么用_控制反转(IoC)与依赖注入(DI)_weixin_39913628的博客-CSDN博客

抽象类是什么?它与接口有什么区别?你为什么要使用过抽象类?

抽象类里的方法可以有具体实现,而接口不能。(即抽象类中的方法不一定全是抽象方法)
一个类只能继承一个抽象类,却可以实现多个接口。
抽象类可以有静态代码块和静态方法,而接口不能。
抽象类中的成员变量可以被不同的修饰符来修饰,可接口中的成员变量默认的都是静态常量
子类中实现父类中的抽象方法时,可见性可以大于等于父类中的;而接口实现类中的接口 方法的可见性只能与接口中相同(public)
 

构造器注入和 setter 依赖注入,那种方式更好?

每种方式都有它的缺点和优点。构造器注入保证所有的注入都被初始化,但是 

setter 注入提供更好的灵活性来设置可选依赖。如果使用 XML 来描述依赖,

Setter 注入的可读写会更强。经验法则是强制依赖使用构造器注入,可选依赖使用 setter 注入。

依赖注入和工程模式之间有什么不同?

虽然两种模式都是将对象的创建从应用的逻辑中分离,但是依赖注入比工程模式 

更清晰。通过依赖注入,你的类就是 POJO,它只知道依赖而不关心它们怎么获 

取。使用工厂模式,你的类需要通过工厂来获取依赖。因此,使用 DI 会比使用 

工厂模式更容易测试。

描述 Java 中的重载和重写?

一、重写:
定义:子类对父类中允许访问的方法的方法体(即方法逻辑)进行重新编写。
意义:增强了类的复用性(即子类可以通过继承拿到父类的东西)、扩展性(即子类按照自己的需要加入自己的东西)
规则:
①方法名不变,即子类必须与父类的方法名称保持一致。
②入参列表不变,即子类必须与父类的入参列表保持一致。
③返回值类型是否可变,需要看所使用的jdk版本。
当是jdk5及以前的版本时,子类与父类的返回值类型必须保持一致。
当是jdk7及以后的版本则可以相同也可以不同,但当不同时则必须保证子类的返回值类型是父类返回值类型的派生类。
④子类不能抛出新异常或者比父类更大的异常,比如当父类的某个方法抛出的是检查异常IOException,那么子类在重写父类方法时就不能抛出Exception,因为Exception是IOException的父类。
⑤子类的访问修饰符级别不能低于父类相应方法的访问权限。
比如当子类与父类在同一包中时,子类可以重写父类中除final或private修饰的所有方法。
当子类与父类不在同一个包中时,子类只能重写父类中public或protected修饰的方法。
⑥当在子类中需要调用父类的方法时,需要使用super关键字调用。
⑦父类的成员方法只能被继承于它的子类所重写。
⑧父类中final声明的成员方法不可以被重写。
⑨父类中static修饰的成员方法也不可以被重写,因为它已经属于类方法了,使用时直接由类调用。但是可以重载。
⑩构造方法不可以被重写,但可以被重载.
二、重载
定义:方法名必须一致,参数列表必须不同(参数的个数或类型不同),返回值类型可以相同也可以不同。即定义在同一类中的两个或多个方法同名但不同参,这就叫做方法的重载。
 

Java 中,嵌套公共静态类与顶级类有什么不同?

类的内部可以有多个嵌套公共静态类,但是一个 Java 源文件只能有一个顶级公 

共类,并且顶级公共类的名称与源文件名称必须一致。

Java 中,throw 和 throws 有什么区别

1、throw 在方法体内使用,throws 在方法声明上使用;
2、throw 后面接的是异常对象,只能接一个。throws 后面接的是异常类型,可以接多个,多个异常类型用逗号隔开;
3、throw 是在方法中出现不正确情况时,手动来抛出异常,结束方法的,执行了 throw 语句一定会出现异常。而 throws 是用来声明当前方法有可能会出现某种异常的,如果出现了相应的异常,将由调用者来处理,声明了异常不一定会出现异常。
 

说出 5 个 JDK 1.8 引入的新特性?

Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性:

Lambda 表达式,允许像对象一样传递匿名函数 

Stream API,充分利用现代多核 CPU,可以写出很简洁的代码 

Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用 

扩展方法,现在,接口中可以有静态、默认方法。

重复注解,现在你可以将相同的注解在同一类型上使用多次。

什么是 Spring IOC 容器?

IOC -- Inverse of Control,控制反转,将对象的创建权力反转给Spring框架

在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况, 比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类出了问题,那么可能会导致这个框架出现问题。 Spring 将创建对象的权利给了IOC,在IOC当中创建了ABC三个对象,那么我们我们其他的类只需要调用集合, 大大的解决了程序耦合性的问题。

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

解决问题:使用IOC可以解决程序耦合性高的问题。

什么是依赖注入?

随着面向对象分析与设计的发展,一个良好的设计,核心原则之一就是将变化隔离,使得变化部分发生变化时,不变部分不受影响(这也是OCP的目的)。为了做到这一点,要利用面向对象中的多态性,使用多态性后,客户类不再直接依赖服务类,而是依赖于一个抽象的接口,这样,客户类就不能在内部直接实例化具体的服务类。但是,客户类在运作中又客观需要具体的服务类提供服务,因为接口是不能实例化去提供服务的。就产生了“客户类不准实例化具体服务类”和“客户类需要具体服务类”这样一对矛盾。为了解决这个矛盾,开发人员提出了一种模式:客户类定义一个注入点,用于服务类(实现IAttackStrategy的具体类,也包括以后加进来的所有实现IAttackStrategy的新类)的注入,而客户类的客户类(Program,即测试代码)负责根据情况,实例化服务类,注入到客户类中,从而解决了这个矛盾。

依赖注入的正式定义:

依赖注入(Dependency Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

spring 中有多少种 IOC 容器?

1、BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
2、ApplicationContext(这个接口经常使用):BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把在配置文件对象进行创建。所以我们着重了解下这个接口。
 

什么是 spring bean?

Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。

Spring 容器会自动完成@bean对象的实例化。

创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。

什么是 spring 的内部 bean?

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML的 配置元数据中,可以在 或  元素内使用 元素,内部bean通常是匿名的,它们的Scope一般是prototype。

自动装配有哪些方式?

byName:
   通过参数名 自动装配
    Spring容器在配置文件中发现bean的autowire属性被设置成byname
     之后容器试图匹配、装配和该bean的属性具有相同名字的bean。

byType:
   通过参数类型自动装配
   Spring容器在配置文件中发现bean的autowire属性被设置成byType
    之后容器试图匹配、装配和该bean的属性具有相同类型的bean
    当有多个bean符合条件,则抛出错误。

constructor:
   这个方式类似于byType,
    但是要提供给构造器参数
    当没有确定的带参数的构造器参数类型,
     将会抛出异常。

autodetect:
    首先尝试使用constructor来自动装配
    当无法工作,则使用byType方式

no:
    默认的方式是不进行自动装配,
    通过显式设置ref 属性来进行装配

spring DAO 有什么用?

Spring DAO 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一 

种统一的方式工作。这使得用户容易在持久性技术之间切换。它还允许您在编写 

代码时,无需考虑捕获每种技术不同的异常。

列举 spring 支持的事务管理类型.

• 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。

• 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置 来管理事务。

什么是 AOP?

AOP为Aspect Oriented Programming的缩写,意思是:面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续。将一些共性的内容进行抽取,在需要用到的地方,以动态代理的方式进行插入,在不修改源码的基础上,还能对源码进行前后增强。
 

什么是切点(JoinPoint)

如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。

Spring MVC 框架有什么用?

目前企业当中有80%的项目使用的都是SpringMVC框架,这么多公司都使用SpringMVC框架来开发项目,SpringMVC框架必然有他的过人之处。今天让我们一起来看看SpringMVC框架是干什么的,有哪些优点。
1、SpringMVC框架的概念

SpringMVC框架是基于MVC模式,使用Java语言开发实现的一个轻量级 Web 框架。它是Spring家族中的一员,和Spring容器是同一个妈妈生的。正因为这一点,通过简单的配置,就能够让SpringMVC框架和Spring容器一起使用。也就是说在基于Spring容器开发的Java web 项目中添加SpringMVC框架,就像给笔记本电脑加装一块固态硬盘。

2、SpringMVC框架的优点

(1)SpringMVC框架提供了一整套完善的组件。

不同于以前框架只提供接口,然后让使用者自己根据接口写实现类来实现功能,SpringMVC提供了一整套完善的组件,可以直接使用。这就相当于以前的框架只给你提供设计图纸,你需要根据设计图纸自己把工具造出来,而现在SpringMVC直接给你一套现成的工具箱,里面有你用得到的各种工具。而且使用SpringMVC框架提供这些工具也巨简单,通过一些简单的注解就搞定了,不需要编写繁琐冗长的代码,简直比夏天喝雪碧还要爽。

(2)SpringMVC是以强大的Spring容器为基础的框架。

如果同学你使用过Spring容器,那你一定知道Spring容器的对象托管功能有多么的好用。它不需要你自己去创建和释放对象,Spring容器帮你全搞定! 同样地,能够放入Spring容器里面的这个SpringMVC工具箱,里面各种工具类的管理也是不需要操心的。而这省心省力的优点,是其他框架都没有的。

(3)框架的配置简单又不失灵活性.

SpringMVC框架的常用配置项就已经涵盖了项目中80%的配置需求,简单的项目甚至可以做到零配置,拿过来就用。

(4)代码的可重用性很高。

翻译成大白话就是,一个成熟的,上线稳定运行过的SpringMVC项目,经过简单修改,甚至不用修改,就可以作为另一个新项目开发的基础。这样能在开发新项目时省很多力气。

(5)可扩展性好。

如果SpringMVC框架提供的工具不能100%满足你的需求,你需要定制开发,SpringMVC框架同样也提供了相应的接口,可以进行工具的升级。这样你在遇到强力精英怪的时候,照样能用SpringMVC框架打败它。

什么是 spring?

1.是一个框架,核心技术是ioc,aop,实现解耦合。
2.spring是一个容器,容器中存放的是java对象,需要做的是对象放入容器中。

使用 Spring 框架的好处是什么?

1.简化开发,解耦,集成其它框架
2.低侵入式设计,代码污染级别低
3.Spring的DI机制降低了业务对象替换的复杂性,提高软件之间的解耦。
4.SpringAOP支持将一些通用的任务进行集中式的管理,例如:安全,事务,日志等,从而使代码能更好的复用。

Spring 由哪些模块组成?

Spring 由七大模块组成,分别是Spring 核心容器(Spring Core)、应用上下文(Spring Context)、Spring面向切面编程(Spring AOP)、JDBC和DAO模块(Spring DAO)、对象实体映射(Spring ORM)、Web模块(Spring Web)以及MVC模块(SpringWebMVC)。
 

解释 AOP 模块

AOP 模块用于发给我们的 Spring 应用做面向切面的开发, 很多支持由 AOP 联 

盟提供,这样就确保了 Spring 和其他 AOP 框架的共通性。这个模块将元数据编 

程引入 Spring。

解释 JDBC 抽象和 DAO 模块

通过使用 JDBC 抽象和 DAO 模块,保证数据库代码的简洁,并能避免数据库资源 错误关闭导致的问题,它在各种不同的数据库的错误信息之上,提供了一个统一的异常访问层。它还利用 Spring 的 AOP 模块给 Spring 应用中的对象提供事务管理服务。

什么是 Spring IOC 容器?

IOC -- Inverse of Control,控制反转,将对象的创建权力反转给Spring框架

在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况, 比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类出了问题,那么可能会导致这个框架出现问题。 Spring 将创建对象的权利给了IOC,在IOC当中创建了ABC三个对象,那么我们我们其他的类只需要调用集合, 大大的解决了程序耦合性的问题。

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

解决问题:使用IOC可以解决程序耦合性高的问题。

解释 Spring 框架中 bean 的生命周期

  1. 通过构造器或工厂方法创建bean实例
  2. 为bean的属性设置值和对其它bean引用
  3. 调用bean的初始化方法
  4. 使用bean
  5. 当容器关闭时,调用bean的销毁方法

哪些是重要的 bean 生命周期方法?你能重载它们吗?

有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown  它是在容器卸载类的时候被调用。

The bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

什么是 bean 的自动装配?

  • no 缺省情况下,自动配置是通过"ref"属性手动设定

  • byName 根据bean的属性名称进行自动装配

    Cutomer的属性名称是person,Spring会将bean id为person的bean通过setter方法进行自动装配。

微服务架构有哪些优势?

1、可扩展性

在增加业务功能时,单一应用架构需要在原先架构的代码基础上做比较大的调整,而微服务架构只需要增加新的微服务节点,并调整与之有关联的微服务节点即可。在增加业务响应能力时,单一架构需要进行整体扩容,而微服务架构仅需要扩容响应能力不足的微服务节点。

2、容错性

在系统发生故障时,单一应用架构需要进行整个系统的修复,涉及到代码的变更和应用的启停,而微服务架构仅仅需要针对有问题的服务进行代码的变更和服务的启停。其他服务可通过重试、熔断等机制实现应用层面的容错。

3、技术选型灵活

微服务架构下,每个微服务节点可以根据完成需求功能的不同,自由选择最适合的技术栈,即使对单一的微服务节点进行重构,成本也非常低。

4、开发运维效率更高

每个微服务节点都是一个单一进程,都专注于单一功能,并通过定义良好的接口清晰表述服务边界。由于体积小、复杂度低,每个微服务可由一个小规模团队或者个人完全掌控,易于保持高可维护性和开发效率。

微服务有哪些特点?

​​​​​​​解耦 – 系统内的服务很大程度上是分离的。因此,整个应用程序可以轻
松构建,更改和扩展
组件化 – 微服务被视为可以轻松更换和升级的独立组件
业务能力 – 微服务非常简单,专注于单一功能
自治 – 开发人员和团队可以彼此独立工作,从而提高速度
持续交付 – 通过软件创建,测试和批准的系统自动化,允许频繁发布软 件
责任 – 微服务不关注应用程序作为项目。相反,他们将应用程序视为他 们负责的产品
分散治理 – 重点是使用正确的工具来做正确的工作。这意味着没有标准
化模式或任何技术模式。开发人员可以自由选择最有用的工具来解决他们的问题
敏捷 – 微服务支持敏捷开发。任何新功能都可以快速开发并再次丢弃

微服务架构的优缺点是什么?

1、开发

需要考虑分布式的复杂性,比如事务和系统容错等。

2、运行

通信成本较高,增加网络延迟。

3、维护

运维难度提升,需要做流量调度、链路监控等。

Spring Boot 中的监视器是什么?

Spring Boot自带监控组件—Actuator,它可以帮助实现对程序内部运行情况的监控。本章首先介绍Actuator轻松实现应用程序的监控治理,比如健康状况、审计、统计和HTTP追踪、Bean加载情况、环境变量、日志信息、线程信息等,然后介绍如何使用Spring Boot Admin构建完整的运维监控平台。
Actuator的核心是端点(Endpoint),它用来监视、提供应用程序的信息,Spring Boot提供的spring-boot-actuator组件中已经内置了非常多的Endpoint(health、info、beans、metrics、httptrace、shutdown等),每个端点都可以启用和禁用。
 

什么是 rabbitmq

RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现 AMQP :Advanced Message Queue高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

为什么要使用 rabbitmq

可靠性(Reliability)RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
灵活的路由(Flexible Routing) 在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个Exchange 绑定在一起,也通过插件机制实现自己的 Exchange
消息集群(Clustering) 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker
高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用
多种协议(Multi-protocol) RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等
多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等
管理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面
跟踪机制(Tracing) 如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么
插件机制(Plugin System) RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件
 

使用 rabbitmq 的场景

1. 异步处理

2. 应用解耦

3. 流量削峰

mq 的缺点

可用性低。这么多系统都在用MQ,那MQ挂了怎么办,那大家不就全挂了吗?

复杂性高。本来大家老老实实的调接口就好了,你现在多加了个MQ,我们还要考虑消息会不会丢失,消息发错了怎么办,消息重复发送了怎么办。

事务一致性问题。比如有一个请求,向A系统内添加数据,A系统让B、C、D三个系统添加数据,B、C两个系统添加成功了,但是D系统突然挂了,这时数据可能就成了非法数据了。

​​​​​​​

猜你喜欢

转载自blog.csdn.net/qq_38935605/article/details/126582004
今日推荐