面试内容
\
- 面试总结
- webService :
- Linux常用命令
- 1. ls:列出文件listList列出当前路径下的文件与文件夹。
- 2. cd:切换目录change directory
- 3. cp:复制copy
- 4. mv:移动move
- 5. rm:移除,删除remove
- 6. mkdir:创建文件夹make directory
- 7. rmdir:移除,删除文件夹remove directory
- 8. chown:更改所有者change owner
- 9. chmod:更改文件的权限模式change mode
- 10. find:查找
- 11. |:管道
- 12. grep:按行查找并匹配
- 13. tar:打包,压缩,解压
- 14. cat:打印文件内容
- 15. ps:查看进程process select
- 16. kill:杀死进程
- 17. passwd:修改密码password
- 18. pwd:显示工作目录print work directory
- 19. tee:显示并保存
- 20. reboot:重启
- 其他命令
- Zookeeper
- Nginx 和负载均衡
- 设计模式
- JVM
- 数据库
- Kafka
- rabbitMq
- 什么是反射(Reflection )?
- JUC---线程创建的三种方式和线程池创建的四种方式
- 常用四种垃圾回收算法
- 类加载过程
- 锁机制
- IOC和AOP
- nacos和eureka的区别
- Undertow和tomcat的区别
面试总结
webService :
https://blog.csdn.net/weixin_39309402/article/details/98127021
1、什么是WebService?或者说webservice能给我们解决什么样的问题?
一句话概括:WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
比如银行端接口基本都是C语言编写,或者财政提供了接口,而银行想要远程调用,假若后端采用Java语言,那么如果想要调用这些接口,WebService就是很好的调用技术之一!
2、WebService的核心是什么?这个问题以前面试的时候遇到过,今天想起来不免有些好笑!当时我真的有些蒙圈,核心?
究竟是指SOAP还是指WSDL?当时直接就说了核心是SOAP协议,其实WebService核心可以归纳为这四个概念:
A.soap:简单对象访问协议,它是轻型协议,用于分散的、分布式计算环境中交换信息。SOAP有助于以独立于平台的方式访问对象、服务和服务器。它借助于XML,提供了HTTP所需的扩展,即http+xml。
B.XML+XSD:WebService平台中表示数据的格式是XML,XML解决了数据表示的问题,但它没有定义一套标准的数据类型,更没有说怎么去扩展这套数据类型,而XSD就是专门解决这个问题的一套标准。它定义了一套标准的数据类型,并给出了一种语言来扩展这套数据类型。
C.wsdl:基于XML用于描述Web Service及其函数、参数和返回值的文件。
WebService服务器端通过一个WSDL文件来说明自己对外提供啥服务,该服务包括什么方法、参数、返回值等等。WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。
客户端要调用一个WebService服务之前,首先要知道该服务的WSDL文件的地址。
3、WebService服务的WSDL文件地址可以通过两种方式来暴露:
1.注册到UDDI服务器,以便被人查找;
2.直接告诉给客户端调用者。
D.uddi:它是目录服务,通过该服务可以注册和发布webservcie,以便第三方的调用者统一调用。
4、如何发布一个webservice?
A.定义SEI(接口) @webservice(类) @webMethod(暴露的方法)
B.定义SEI的实现
C.发布Endpoint.publish(url,new SEI的实现对象)
5、如何请求一个webservice?
A.根据wsdl文档生成客户端代码
jdk wsimport -keep wsdl路径
cxf wsdl2java wsdl路径
B.根据生成的代码调用webservice
找到wsdl文档中service标签的name属性对应的类,找到这个port标签的name属性,调用该方法即可
6、WebService常用开发框架
Apache Axis1、Apache Axis2、Codehaus XFire、Apache CXF、Apache Wink、Jboss RESTEasy、sun JAX-WS(最简单、方便)、阿里巴巴 Dubbo等。
Linux常用命令
https://blog.csdn.net/Dabie_haze/article/details/118969328
- ls: 列出文件list
- cd: 切换目录change directory
- cp: 复制copy
- mv: 移动move
- rm: 移除,删除remove
- mkdir: 创建文件夹make directory
- rmdir: 移除,删除文件夹remove directory
- chown: 更改所有者change owner
- chmod: 更改文件的权限模式change mode
- find: 查找
- |: 管道
- grep: 按行查找并匹配
- tar: 打包,压缩,解压
- cat: 打印文件内容
- ps: 查看进程process select
- kill: 杀死进程
- passwd: 修改密码password
- pwd: 显示工作目录print work directory
- tee: 显示并保存
- reboot: 重启
1. ls:列出文件listList列出当前路径下的文件与文件夹。
ls 参数及用法:redis 事务传播机制
-l:列出文件的详细信息
-a:all,列出所有文件,包括隐藏文件
注:参数可以叠加使用,如-la表示列出所有文件及其详细信息
2. cd:切换目录change directory
cd用法
cd /home # 切换/进入home目录
cd .. # 到上一目录(父目录)
cd ../.. # 到父目录的父目录
cd . # 进入当前目录(其实啥都不做)
3. cp:复制copy
cp 参数及用法:
-i:interactive mode,若有同名文件,会询问是否覆盖(如果没这个参数,会不提示,直接覆盖)
-r:recursive copy,复制文件夹时连同子文件(夹)一起复制,如果是对文件夹进行操作,一定要带这个参数
例:
cp -ir sourceDir/ home/targetDir/ # 把当前路径下的sourceDir文件夹复制到home目录下,取名为targetDir,且带参数-i和-r
4. mv:移动move
即剪切操作。源文件会被删除。
mv 参数及用法:
-i: interactive mode,同cp的-i参数,若覆盖会询问
例:
mv -i sourceFile /home/targetFile # 把当前目录下的sourceFile剪切到/home目录下并命名为targetFile
5. rm:移除,删除remove
rm 参数及用法:
-i:interactive,同上,若覆盖,先询问
-r:recursive mode,删除所有子文件(夹)
例:
rm Dir/ # 删除Dir文件夹(错误示例,会报错)
rm -r Dir/ # 删除Dir文件夹(正确,对文件夹操作一定要带-r)
6. mkdir:创建文件夹make directory
mkdir用法
mkdir newDir/ # 在当前路径创建一个空文件夹newDir/
7. rmdir:移除,删除文件夹remove directory
rmdir用法
rmdir oldDir/ # 在当前路径删除oldDir文件夹及其子文件(夹)
8. chown:更改所有者change owner
chown 参数及用法:
-R: 同-r,recursive
例:
chown user -R myDir/ # 把文件夹myDir的所有者改成user
9. chmod:更改文件的权限模式change mode
文件权限模式针对三类对象:
当前用户user(这里也是文件的所有者),组group,其他用户other。
文件权限有读Read,写Write,执行Execute。
chmod参数及用法:
u: user,权限对象为当前用户(这里是所有者)
g:group,权限对象为所有者和组
o:other,权限对象为其他用户
r:read = 4,读权限
w:write = 2,写权限
e:execute = 1,执行权限
+:u/g/o与r/w/e组合使用,加入
-:删除
=:设置
4:仅读
5:仅读+执行
6:仅读+写
7:读+写+执行
chmod用法
chmod 754 myDir/ # 当前用户(所有者)可读+写+执行,组group可读+执行,其他用户可读
chmod g+w myDir/ # 为组group添加写write权限
chmod -R 777 myDir/ # 给myDir/及其所有子目录添加所有权限
ls -n # 可以查看当前目录下各子目录的文件权限
10. find:查找
find 参数及用法:
-name:根据文件名查找
-mtime n:n为数字,表示找出在n天前的当天被更改过的文件(0表示今天)
-mtime +n:查找在n天前(不包括n天当天)被改过的文件
-mtime -n:查找在n天之内(包括n天当天)被改过的文件
-size +/-:查找比XXsize大/小的文件
例:
find /home -name myFile # 在/home目录下查找文件名为myFile的文件(注:myFile也可以搭配正则表达式使用)
find /home -name *.txt # 在/home目录下查找以txt为后缀的文件
find /home -mtime 0 # 在/home目录下查找今天内被改过的文件
find /home -mtime +1 # 在/home目录下查找昨天之前(不包括昨天)被改过的文件
find /home -mtime -1 # 在/home目录下查找昨天至今(即昨天和今天)被改过的文件
find /home -size +100M # 在/home目录下查找大于100MB的文件,注意c表示byte
11. |:管道
将前一个命令的输出结果像管道一样传递给后一个命令作为输入
管道|用法
ls | find -name myFile # 列出当前路径的文件(夹)并查找名字为“myFile”的,打印出来
12. grep:按行查找并匹配
grep参数及用法:
-r:recursive,查找所有子文件(夹)
-n:number,显示行号
-w:word,完整匹配整个单词
-i:insensitive search,忽略大小写
-l:显示文件名称,而非匹配到的行的内容
-v:反向选择,显示出没匹配到的行的内容
grep用法
grep -i mystring file.txt # 忽略大小写,在file.txt中查找并打印出有“mystring”的行
ls -l | grep -i mystring # 在ls -l的输出中把有“mystring”的行打印出来(忽略大小写)
13. tar:打包,压缩,解压
tar参数
-jcv:压缩
-jxv:解压
tar用法
tar -jcv myDir/ # 压缩myDir文件夹
tar -jxv DownloadDir.tar.gz myDir/ # 解压DownloadDir.tar.gz到当前文件夹下,并命令为myDir
14. cat:打印文件内容
cat用法
cat myFile # 显示myFile
15. ps:查看进程process select
ps 参数及用法:
-A:显示所有进程
-a:不与terminal有关的所有进程
-u:有效用户的相关进程
-x:一般与-a一起用,列出完整的进程信息
-l:long,详细列出PID的信息
例:
ps Aux # 查看系统所有的进程数据
ps ax
16. kill:杀死进程
kill参数及用法:
-SIGHUP:启动被终止的进程
-SIGINT:相当于ctrl+c,中断进程
-SIGKILL:强制中断进程
-SIGTERM:以正常的结束进程方式来终止进程
-SIGSTOP:相当于ctrl+z,暂停进程
例:
kill -SIGKILL 10876 # 强制中断PID=10876的进程(PID可以通过ps查到,有时可以加上| grep进行筛选)
17. passwd:修改密码password
passwd用法
passwd # 修改当前用户的密码
18. pwd:显示工作目录print work directory
pwd用法
pwd # 显示当前路径的具体位置
19. tee:显示并保存
显示内容并将内容保存在文件中。
python3.6 test.py | tee result.log # 运行test.py文件,显示编译与运行结果并保存成result.log文件
20. reboot:重启
reboot用法
reboot # 输完立马重启(记得保存文件)
其他命令
alias 设置别名
alias cp='cp -i' # 输入cp默认调用cp -i
alias rm='rm -i'
alias mv='mv -i'
bg查看后端运行的进程 background
bg #会显示后端进程的号码
kill %1 #强制杀死1号进程
touch创建新文件
touch new_file.txt # 创建一个new_file.txt文件
du -h 打印文件/文件夹的大小
du -h #打印当前目录下所有子目录与子文件夹的大小
du -h --max-depth=0 #打印当前目录的大小
du -h --max-depth=1 #打印当前目录下所有子目录的大小
Zookeeper
https://blog.csdn.net/woniu211111/article/details/123331903
Paxos 算法
Nginx 和负载均衡
https://www.runoob.com/w3cnote/nginx-setup-intro.html
特点:
热部署
高并发
低内存
快响应
可靠性
功能:
反向代理
负载均衡
动静分离
设计模式
https://blog.csdn.net/zhaohongfei_358/article/details/115085887
JVM
https://blog.csdn.net/ashfiqa/article/details/122658797
https://blog.csdn.net/weixin_43122090/article/details/105093777
https://blog.csdn.net/qq_41701956/article/details/81664921
线程和进程的关系
线程定义
线程是进程的基本执行单元,一个进程的所有任务都在线程中执行
进程要想执行任务,必须得有线程,进程至少要有一条线程
程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程
进程定义
进程是指在系统中正在运行的一个应用程序
每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存
进程与线程的区别
地址空间:
同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
资源拥有:
同一进程内的线程共享本进程的资源(如内存、I/O、cpu等),但是进程之间的资源是独立的。
一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
执行过程:
每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
线程是处理器调度的基本单位,但是进程不是。
多线程的意义
优点
能适当提高程序的执行效率
能适当提高资源的利用率(CPU,内存)
线程上的任务执行完成后,线程会自动销毁
缺点
开启线程需要占用一定的内存空间(默认情况下,每一个线程都占 512 KB)
如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,CPU 在调用线程上的开销就越大
程序设计更加复杂,比如线程间的通信、多线程的数据共享
数据库
数据库引擎
https://blog.csdn.net/fuhanghang/article/details/124147367
Mysql
1. MySQL 索引使用有哪些注意事项呢?
可以从三个维度回答这个问题:索引哪些情况会失效,索引不适合哪些场景,索引规则
聚簇索引
https://blog.csdn.net/u012135155/article/details/104203070
聚簇索引(Cluster Index)也叫索引组织表(Index-organized Table),MySQL用户经常称呼为前者。聚簇索引并不是数据库索引的某个种类,其描述的是数据的一种存储方式。我们知道,在InnoDB中,数据是以B+Tree的形式存储的,其特点就是数据都存储在叶子节点上,非叶子节点上只存索引信息,即key值和指向子节点的指针。这种索引和数据的存储方式就叫做聚簇索引,“聚簇”的意思就是通常来说,数据行和相邻的健挨着。
InnoDB通过主键来聚集数据,也就是说聚簇索引的B+Tree上的叶子结点所存储的key总是主键,如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,InnoDB会隐式地定义一个主键来聚集(存储)数据,这个隐式的主键被称为rowID。
在InnoDB中,存储聚簇索引的B+Tree的叶子节点是一个数据页,默认大小为16K,这些数据页上的数据其实是一个有序链表,会按照主键递增的顺序来进行存储。在上图中,如果要访问ID为10的记录,InnoDB根据索引找到了key为11的索引,访问其左子节点,然后进行遍历(由于在一个数据页中的数据的存放位置是连续的,所以不会有多次寻址的额外开销),比较key值直到找到ID为10的记录。
对于非聚簇索引,InnoDB通常在叶子节点上存储的是数据行的主键值,命中非聚簇索引时,InnoDB会拿到此主键值再去聚簇索引中查询所需要的记录,这个过程称为回表。正是由于如此,所以通常来说聚簇索引的查询效率要比非聚簇索引高。
索引哪些情况会失效
https://blog.csdn.net/tfstone/article/details/81197921
查询条件包含or,可能导致索引失效
如何字段类型是字符串,where时一定用引号括起来,否则索引失效
like通配符可能导致索引失效。
联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
在索引列上使用mysql的内置函数,索引失效。
对索引列运算(如,+、-、*、/),索引失效。
索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
索引字段上使用is null, is not null,可能导致索引失效。
左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
mysql估计使用全表扫描要比使用索引快,则不使用索引。
索引的种类
索引有哪些种类?
MySQL中的索引分为很多种,具体如下。
1.普通索引
普通索引是由KEY或INDEX定义的索引,它是MySQL中的基本索引类型,可以创建在任何数据类型中,其值是否唯一和非空由字段本身的约束条件所决定。例如,在grade表的stu_id字段上建立一个普通索引,查询记录时,就可以根据该索引进行查询了。
2.唯一性索引
唯一性索引是由UNIQUE定义的索引,该索引所在字段的值必须是唯一的。例如,在grade表的id字段上建立唯一性索引,那么,id字段的值就必须是唯一的。
3.全文索引
全文索引是由FULLTEXT定义的索引,它只能创建在CHAR、VARCHAR或TEXT类型的字段上,而且,现在只有MyISAM存储引擎支持全文索引。
4.单列索引
单列索引指的是在表中单个字段上创建索引,它可以是普通索引、唯一索引或者全文索引,只要保证该索引只对应表中一个字段即可。
5.多列索引
多列索引指的是在表中多个字段上创建索引,只有在查询条件中使用了这些字段中的第一个字段时,该索引才会被使用。例如,在grade表的id、name和score字段上创建一个多列索引,那么,只有查询条件中使用了id字段时,该索引才会被使用。
6.空间索引
空间索引是由SPATIAL定义的索引,它只能创建在空间数据类型的字段上。MySQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING和POLYGON。需要注意的是,创建空间索引的字段,必须将其声明为NOT NULL,并且空间索引只能在存储引擎为MyISAM的表中创建。
需要注意的是,虽然索引可以提高数据的查询速度,但索引会占用一定的磁盘空间,并且在创建和维护索引时,其消耗的时间是随着数据量的增加而增加的。因此,使用索引时,应该综合考虑索引的优点和缺点。
索引不适合哪些场景
数据量少的不适合加索引
更新比较频繁的也不适合加索引
区分度低的字段不适合加索引(如性别)
索引的一些潜规则
覆盖索引
回表
索引数据结构(B+树)
最左前缀原则
索引下推
2. MySQL 遇到过死锁问题吗,你是如何解决的?
我排查死锁的一般步骤是酱紫的:
查看死锁日志show engine innodb status;
找出死锁Sql
分析sql加锁情况
模拟死锁案发
分析死锁日志
分析死锁结果
3.日常工作中你是怎么优化SQL的?
可以从这几个维度回答这个问题:
加索引
避免返回不必要的数据
适当分批量进行
优化sql结构
分库分表
读写分离
4. 说说分库与分表的设计
分库分表方案,分库分表中间件,分库分表可能遇到的问题
分库分表方案:
水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
5.分库分表可能遇到的问题
事务问题:需要用分布式事务啦
跨节点Join的问题:解决这一问题可以分两次查询实现
跨节点的count,order by,group by以及聚合函数问题:分别在各个节点上得到结果后在应用程序端进行合并。
数据迁移,容量规划,扩容等问题
ID问题:数据库被切分后,不能再依赖数据库自身的主键生成机制啦,最简单可以考虑UUID
跨分片的排序分页问题(后台加大pagesize处理?)
5. InnoDB与MyISAM的区别
InnoDB支持事务,MyISAM不支持事务
InnoDB支持外键,MyISAM不支持外键
InnoDB 支持 MVCC(多版本并发控制),MyISAM 不支持
MVCC是多版本并发控制机制,顾名思义支持MVCC的数据库表中每一行数据都可能存在多个版本,对数据库的任何修改的提交都不会直接覆盖之前的数据,而是产生一个新的版本与老版本共存,通过读写数据时读不同的版本来避免加锁阻塞。MVCC的实现主要依赖于数据库在每个表中添加的三个隐藏字段以及事务在查询时创建的快照(read view)和数据库的数据版本链(Undo log)。
DB_TRX_ID(6字节): 它是最近一次更新或者插入或者删除该行数据的事务ID(若是删除,则该行有一个删除位更新为已删除。但并不是真正的进行物理删除,当InnoDB丢弃为删除而编写的更新撤消日志记录时,它才会物理删除相应的行及其索引记录。此删除操作称为清除,速度非常快)
DB_ROLL_PTR(7字节): 回滚指针,指向当前记录行的undo log信息(指向该数据的前一个版本数据)
DB_ROW_ID(6字节): 随着新行插入而单调递增的行ID。
select count(*) from table时,MyISAM更快,因为它有一个变量保存了整个表的总行数,可以直接读取,InnoDB就需要全表扫描。
Innodb不支持全文索引,而MyISAM支持全文索引(5.7以后的InnoDB也支持全文索引)
InnoDB支持表、行级锁,而MyISAM支持表级锁。
InnoDB表必须有主键,而MyISAM可以没有主键
Innodb表需要更多的内存和存储,而MyISAM可被压缩,存储空间较小,。
Innodb按主键大小有序插入,MyISAM记录插入顺序是,按记录插入顺序保存。
InnoDB 存储引擎提供了具有提交、回滚、崩溃恢复能力的事务安全,与 MyISAM 比 InnoDB 写的效率差一些,并且会占用更多的磁盘空间以保留数据和索引
二叉树 、平衡二叉树、红黑树、B树、B+树与B*树
https://blog.csdn.net/ChineseSoftware/article/details/123737235
ES 注解 paxos算法 hashmap 树 seata mysql数据库 反射
乐观锁 默认没修改 适合写少读多
悲观锁 默认已修改 适合写多读少
Kafka
kafka和rabbitMq的区别 https://qqe2.com/java/post/751.html
零拷贝 https://blog.csdn.net/li1669852599/article/details/114143295
零拷贝:将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件
前提条件
任何消息组件不丢数据都是在特定场景下一定条件的,kafka要保证消息不丢,有两个核心条件。
第一,必须是已提交的消息,即committed message。kafka对于committed message的定义是,生产者提交消息到broker,并等到多个broker确认并返回给生产者已提交的确认信息。而这多个broker是由我们自己来定义的,可以选择只要有一个broker成功保存该消息就算是已提交,也可以是令所有broker都成功保存该消息才算是已提交。不论哪种情况,kafka只对已提交的消息做持久化保证。
第二,也就是最基本的条件,虽然kafka集群是分布式的,但也必须保证有足够broker正常工作,才能对消息做持久化做保证。也就是说 kafka不丢消息是有前提条件的,假如你的消息保存在 N 个kafka broker上,那么这个前提条件就是这 N 个broker中至少有 1 个存活。只要这个条件成立,kafka就能保证你的这条消息永远不会丢失。
如何保证消息不丢
一条消息从产生,到发送到kafka保存,到被取出消费,会有多个场景和流程阶段,可能会出现丢失情况,我们聊一下kafka通过哪些手段来保障消息不丢。
生产端
Producer端可能会丢失消息。目前Kafka Producer是异步发送消息的,也就是说如果你调用的是producer.send(msg)这个API,那么它通常会立即返回,但此时你不保证消息发送已成功完成。可能会出现:网络抖动,导致消息压根就没有发送到Broker端;或者消息本身不合规导致Broker拒绝接收(比如消息太大了,超过了Broker的限制)。
实际上,使用producer.send(msg, callback)接口就能避免这个问题,根据回调,一旦出现消息提交失败的情况,就可以有针对性地进行处理。如果是因为那些瞬时错误,Producer重试就可以了;如果是消息不合规造成的,那么调整消息格式后再次发送。总之,处理发送失败的责任在Producer端而非Broker端。当然,如果此时broker宕机,那就另当别论,需要及时处理broker异常问题。
消费端
Consumer端丢数据的情况,稍微复杂点。Consumer有个”位移“(offset)的概念,表示Consumer当前消费到topic分区的哪个位置。
锁
Sychronized 和 lock的区别
1.首先synchronized是java内置关键字,在jvm层面,
Lock是个java提供的一个接口;
2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;
b 线程执行过程中发生异常会释放锁),
Lock需在finally中手工释放锁(unlock()方法释放锁),
否则容易造成线程死锁;
4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,
线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,
而Lock锁就不一定会等待下去,如果尝试获取不到锁,
线程可以不用一直等待就结束了;
5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、
可判断、可公平(两者皆可)
6.Lock锁适合大量同步的代码的同步问题,
synchronized锁适合代码少量的同步问题
- 在竞争不是很激烈的情况下,也就是线程数量比较少的情况下,sychornized的性能要优于lock,但是在竞争很激烈的情况下 。 sychornized的性能会下降,lock的性能能维持常态
rabbitMq
丢数据的三个场景:生产者丢失,mq自己丢失,消费者丢失
生产者丢失:
第一种消息发送前开启事务,发生异常就回滚事务
第二种开启confirm模式,每次写得消息都会分配一个唯一的id,写入mq之后会回传acK消息,失败回调用nack接口,可以根据这重新处理这个消息
两种处理方式的区别:事务机制是同步的,提交一个事务会阻塞的,而confirm机制是异步的,发送消息之后还能发送下一个消息,一般使用confirm 机制
mq丢失:
对消息队列和交换机持久化,并且发送消息的是deliveryMode 设置为2(1是不持久化)
消费者丢失:
a、丢失的原因:如果RabbitMQ成功的把消息发送给了消费者,那么RabbitMQ的ack机制会自动的返回成功,表明发送消息成功,下次就不会发送这个消息。但如果就在此时,消费者还没处理完该消息,然后宕机了,那么这个消息就丢失了。
b、解决的办法:简单来说,就是必须关闭 RabbitMQ 的自动 ack,可以通过一个 api 来调用就行,然后每次在自己代码里确保处理完的时候,再在程序里 ack 一把。这样的话,如果你还没处理完,不就没有 ack了?那 RabbitMQ 就认为你还没处理完,这个时候 RabbitMQ 会把这个消费分配给别的 consumer 去处理,消息是不会丢的。
JVM可以分为3大部分:类加载器,运行时数据区和执行引擎。
类加载器负责加载字节码文件,即java编译后的 .class 文件。
运行时数据区负责存放.class 文件,分配内存。运行时数据区又分为5个部分:方法区:负责存放.class 文件,方法区里有一块区域是运行时常量池,用来存放程序的常量。
堆:分配给对象的内存空间。
方法区和堆是所有线程共享的内存空间。java虚拟机栈:每个线程独享的内存空间。
本地方法栈:本地native 方法独享的内存空间。
程序计数器:记录线程执行的位置,方便线程切换后再次执行。
java虚拟机栈,本地方法栈,程序计数器是每个线程独享的。
sleep的作用
sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行。
wait的作用
调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。
sleep与wait差异总结
1、来自不同的类:sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。
2、有没有释放锁(释放资源):sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。
3、一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
什么是反射(Reflection )?
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
Java反射?
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法
Class c1 = Student.class;
Class c2 = new Student().getClass();
Class c3 = Class.forName("day16.Student");
Java反射机制主要提供了以下功能:
* 1.在运行时判断任意一个对象所属的类。
* 2.在运行时构造任意一个类的对象。
* 3.在运行时判断任意一个类所具有的成员变量和方法。
* 4.在运行时调用任意一个对象的方法。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
JUC---线程创建的三种方式和线程池创建的四种方式
1.1线程创建的方式
java创建线程的三种方式:
1.继承Thread类创建线程类
2.实现Runnable接口
3.通过Callable和Future创建线程
(1)Callable规定的方法是call(),Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(3)call方法可以抛出异常,run方法不可以,因为run方法本身没有抛出异常,所以自定义的线程类在重写run的时候也无法抛出异常
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
AsyncConfigurer
内存调优:
-Xms、-Xmx分配用来设置进程堆内存的最小大小和最大大小。
-Xmn用来设置堆内新生代的大小。
-Xss设置每个线程可使用的内存大小。
常用四种垃圾回收算法
常用的垃圾回收算法有四种:标记-清除算法、复制算法、标记-整理算法、分代收集算法。
1.标记-清除算法
分为标记和清除两个阶段,首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象,如下图。
缺点:标记和清除两个过程效率都不高;标记清除之后会产生大量不连续的内存碎片。
2.复制算法
把内存分为大小相等的两块,每次存储只用其中一块,当这一块用完了,就把存活的对象全部复制到另一块上,同时把使用过的这块内存空间全部清理掉,往复循环,如下图。
缺点:实际可使用的内存空间缩小为原来的一半,比较适合。
3.标记-整理算法
先对可用的对象进行标记,然后所有被标记的对象向一段移动,最后清除可用对象边界以外的内存
4.分代收集算法
把堆内存分为新生代和老年代,新生代又分为 Eden 区、From Survivor 和 To Survivor。一般新生代中的对象基本上都是朝生夕灭的,每次只有少量对象存活,因此采用复制算法,只需要复制那些少量存活的对象就可以完成垃圾收集;老年代中的对象存活率较高,就采用标记-清除和标记-整理算法来进行回收。
类加载过程
加载——验证——准备——解析——初始化——卸载
类加载阶段:
(1)Java虚拟机将.class文件读入内存,并为之创建一个Class对象。
(2)任何类被使用时系统都会为其创建一个且仅有一个Class对象。
(3)这个Class对象描述了这个类创建出来的对象的所有信息,比如有哪些构造方法,都有哪些成员方法,都有哪些成员变量等。
验证
验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。
文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。
元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范要求
字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。
符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。
准备
准备阶段为变量分配内存并设置类变量的初始化。
解析
解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。
初始化
初始化,则是为标记为常量值的字段赋值的过程。换句话说,只对static修饰的变量或语句块进行初始化。
on duplicate key update
锁机制
互斥锁: mutex,用于保证在任何时刻,都只能有一个线程访问该对象。
当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒
读写锁: rwlock,分为读锁和写锁。处于读操作时,可以允许多个线程
同时获得读操作。但是同一时刻只能有一个线程可以获得写锁。其它获
取写锁失败的线程都会进入睡眠状态,直到写锁释放时被唤醒。 注意:
写锁会阻塞其它读写锁。当有一个线程获得写锁在写时,读锁也不能被
其它线程获取;写者优先于读者(一旦有写者,则后续读者必须等待,
唤醒时优先考虑写者)。适用于读取数据的频率远远大于写数据的频率
的场合。
自旋锁: spinlock,在任何时刻同样只能有一个线程访问对象。但是当获取锁
操作失败时,不会进入睡眠,而是会在原地自旋,直到锁被释放。这样节省了
线程从睡眠状态到被唤醒期间的消耗,在加锁时间短暂的环境下会极大的提高
效率。但如果加锁时间过长,则会非常浪费CPU资源。
RCU: 即read-copy-update,在修改数据时,首先需要读取数据,然后生成一个副
本,对副本进行修改。修改完成后,再将老数据update成新的数据。使用RCU时,
读者几乎不需要同步开销,既不需要获得锁,也不使用原子指令,不会导致锁竞争
,因此就不用考虑死锁问题了。而对于写者的同步开销较大,它需要复制被修改的
数据,还必须使用锁机制同步并行其它写者的修改操作。在有大量读操作,少量写
操作的情况下效率非常高。
SpringBoot启动过程主要分为bootstrapContext创建、环境准备、applicationContext准备、bean加载、runner调用五个步骤
第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,
第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块,
第三部分是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。在下面的启动程序中我们会串联起结构中的主要功能。
当AOF持久化功能处于打开状态时,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾
聚簇索引
bean生命周期
springboot加载方式
redis配置方式
索引
IOC和AOP
https://blog.csdn.net/javalingyu/article/details/124099070
nacos和eureka的区别
https://baijiahao.baidu.com/s?id=1726153682148849581
spring 事务传播机制
Spring的事务传播机制定义了在多个事务操作之间如何管理事务边界,以确保数据的一致性和完整性。Spring提供了多种事务传播级别,每个级别用于不同的应用场景。以下是Spring事务传播机制的常见传播级别:
propagation_required:默认级别。如果当前没有事务,新事务将被启动。如果存在当前事务,则加入该事务。这是最常见的传播级别,适用于大多数情况。
propagation_requires_new:始终启动一个新事务。如果当前存在事务,则将其挂起,然后启动新事务。这个级别适用于需要独立事务的情况,即使外部事务失败,内部事务也会提交。
propagation_nested:如果当前没有事务,新事务将被启动。如果当前存在事务,新事务将嵌套在当前事务中,作为当前事务的嵌套事务。这个级别适用于需要嵌套事务,内部事务可以独立提交或回滚,而不影响外部事务。
propagation_supports:如果当前存在事务,就加入该事务;如果没有,就以非事务方式执行。这个级别适用于不需要强制事务的情况。
propagation_not_supported:以非事务方式执行,如果当前存在事务,则将其挂起。这个级别适用于不需要事务的情况。
propagation_mandatory:如果当前存在事务,就加入该事务;如果没有,抛出异常。这个级别用于要求某个方法在事务内部运行的情况。
propagation_never:以非事务方式执行,如果当前存在事务,抛出异常。这个级别用于要求某个方法在没有事务的情况下运行。
这些传播级别允许您根据应用程序的需求灵活地管理事务。您可以在Spring的@Transactional注解中设置propagation属性,或者在XML配置中使用<tx:advice>元素来指定事务传播级别。不同的传播级别适用于不同的业务场景,可以帮助您确保事务行为的一致性和可控性。数据库 事务隔离级别
连接池的7种方式和7个参数
redis 事务
数据库连接层
聚簇索引
手写一个简单的Starter
threadlocal
JAVA - JUC
https://blog.csdn.net/weixin_43888181/article/details/116546374
spring三级缓存 和 循环依赖
浙公网安备 33010602011771号