一.有用到模糊查询吗?怎么用的?
[]:匹配括号内所列字符中的1个,类似正则表达式。
select * from table_name where name like ‘[ABC]D’
select * from table_name where name like ‘%COM’
二.索引?
索引的目的在于提高查询效率,索引存储在磁盘文件里,索引的数据结构是B+树,使用B+树是为了减少IO。(一张表中,id不是索引,只是一个字段,但若给id加了primary key,id就变成了索引了)
聚簇索引:找到了索引就找到了需要的数据,那么这个索引就是聚簇索引,所以主键就是聚簇索引,修改聚簇索引其实就是修改主键。
The InnoDB term for a primary key index.
非聚簇索引:索引的存储和数据的存储是分离的,也就是说找到了索引(比如unique key)但没找到数据,需要根据索引上的值(主键)再次回表查询,非聚簇索引也叫做辅助索引。
总结:主键一定是聚簇索引(MyisAM引擎没有聚簇索引),,其它普通索引需要区分SQL场景。
索引优点:提高查询效率,减少IO(内外存交互)。
索引缺点:索引也要占空间;有了更新表的速度成本,对数据进行增删改时需要更新变化。(这也是为什么不能全部字段都加索引的原因,太占空间,而且当索引过多对于写操作也会浪费时间)
你知道什么索引?
主键(聚簇索引)、唯一索引(加unique,特点是索引列的值必须唯一,但允许有多个null)、复合索引(一个索引包含多个列,有个左前缀特性(别提了))、普通索引(就是直接add index myIdxName(列))、全文索引(add fulltext我的理解是和like的作用相似)
索引的创建:
create index myIdxName on myTable(myColofTable);
show index from myTable;
drop index myIdxName on myTable;
三.B树和B+树?
查询过程:B+树的查询与B树大致上一样,但不同的是在B+树里面查找必须找到叶节点层才行,因为B+树里面最底层的叶节点才是全集,而在B树里面非叶子节点也可以存储数据,所以直接查询遇到查找的值就返回。
B+树的两种查询方式:
(1)从root出发一直查询到叶节点。
(2)从叶节点的最左侧出发,进行顺序查找,这个比较适合迭代输出全量数据(或范围查找)的时候使用。
为什么用B+而不用B:
(1)范围查询
(2)做排序 desc时
补:一棵三层的B+树能存多少数据量?
Innodb的最小存储单位,页,大小为16k
除了叶子节点存数据,其他节点存的是主键(排序)和指针。大小为bigint8字节,指针6字节,一共14个字节
单个叶子节点存的数据一般为16条。(一行数据大约为1k)
所以高度为2的b+树:16348(16k)/14=1170, 117016=18720,约2万条数据
所以高度为3的b+树:11701170*16,约2千万条数据
四. 二叉搜索树 平衡二叉树 红黑树?
红黑树与B树(2-3树是三阶B树,2-3-4树是4阶B树)联系:红黑树其实就是对概念模型2-3树(或者2-3-4树)的一种实现。
五. GROUP BY和聚合函数?
join等价于inner join内连接抄,是返回两个表中都有的符合条件的行。
left join左连接,是返回左袭表知中所有的行及右表中符合条件的行。
right join右连接,是返回右表中所有的行及左表中符合条件的行。
MAX() 函数返回指定列的最大值。
GROUP BY 语句可结合一些聚合函数来使用,如count(), sum()
六. 组合两个表?
解题步骤:
1)查询结果是两个表里的列名,所以需要多表查询
2)考虑到有的人可能没有地址信息,要是查询结构要查所有人,需要保留表1(Person)里的全部数据,所以用左联结(left join)
3)两个表联结条件:两个表通过personId产生联结。
select FirstName, LastName, City, State
from Person
left join Address
on Person.PersonId = Address.PersonId;
select ifNull((select distinct Salary
from Employee
order by Salary desc
limit 1,1),null) as SecondHighestSalary;
八. innodb特性?
InnoDB的内存架构主要分为三大块,缓冲池(Buffer Pool)、重做缓冲池(Redo Log Buffer)和额外内存池。
九. innodb与MyISAM的区别?
总结:MyISAM只适用于查询大于更新的场景
十. 谈谈你对Mysql的MVCC的理解?
Multi-Version Concurrency Control, 多版本并发控制。
发展过程:读写锁,读锁和读锁之间不互斥,而写锁和写锁、读锁都互斥。并发读还不够,又提出了能不能让读写之间也不冲突的方法,就是读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了。
运行条件:MVCC只在 READ COMMITTED和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级别够和MVCC不兼容, 因为 READ UNCOMMITTED 总是读取最新的数据行, 而不是符合当前事务版本的数据行。而 SERIALIZABLE 则会对所有读取的行都加锁。
解释:用到版本链 and 聚簇索引记录中有两个必要的隐藏列:trx_id, roll_pointer。已提交读和可重复读的区别就在于它们生成ReadView的策略不同。对于已提交读,每次都重新生成一个ReadView,然后顺着链找上一个。对于可重复读,则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView。
十一. innodb事务日志undo log和redo log?mysql的bin log日志?
MVCC 的多版本指的是多个版本的快照,快照存储在 Undo 日志中,该日志通过回滚指针 ROLL_PTR 把一个数据行的所有快照连接起来。
具体解释:首先我们先明确一下InnoDB的修改数据的基本流程,当我们想要修改DB上某一行数据的时候,InnoDB是把数据从磁盘读取到内存的缓冲池上进行修改。这个时候数据在内存中被修改,与磁盘中相比就存在了差异,我们称这种有差异的数据为脏页。InnoDB对脏页的处理不是每次生成脏页就将脏页刷新回磁盘,这样会产生海量的IO操作,严重影响InnoDB的处理性能。对于此,InnoDB有一套完善的处理策略。既然脏页与磁盘中的数据存在差异,那么如果在这期间DB出现故障就会造成数据的丢失。为了解决这个问题,redo log就应运而生了。
具体解释:任何时间对数据库的修改都会记录在bin log(二进制日志,逻辑日志)中。当数据发生增删改,创建数据库对象都会记录到binlog中,数据库的复制也是基于binlog进行同步数据。它记录了所有的 DDL 和 DML 语句(除了数据查询语句select、show等),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。binlog 的主要目的是复制和恢复。
补:
崩溃断电场景:恢复机制会将redo log中已提交的事务重做,保证事务的持久性;而undo log中未提交的事务进行回滚,保证事务的原子性。
mysql实现一致性:一致性就是:应用系统从一个正确的状态到另一个正确的状态.而ACID就是说事务能够通过AID来保证这个C的过程.C是目的,AID都是手段
隔离性:mvcc和锁机制去实现的(四种隔离级别)。
十二. select count(*) from table 时间是常数级吗?
只知道,MySQL里面的MyISAM引擎做全表count特别快
阿里java开发手册sql规约第一条:不要使用 count(列名)或 count(常量)来替代 count( * ),count( * )就是 SQL92 定义 的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。 说明:count( * )会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
十三. mysql中int(10)和char(10),varchar(10)的10代表什么?
十四. 联合索引的最左匹配原则?
复合索引(abc) 所有情况的罗列:
abc 能用到索引
bca 能用到索引(优化器)
cab 能用到索引(优化器)
ab 能用到索引
ac 能用到索引(这样好像虽然a会用到索引,但c用不到索引)
ba 能用到索引(优化器)
ca 能用到索引(优化器,这样好像虽然a会用到索引,但c用不到索引)
bc 用不到索引
b 用不到索引
c 用不到索引
cb 用不到索引
十五. 覆盖索引(解决回表问题)?
如果查询条件为普通索引(非聚簇索引),需要扫描两次B+树,第一次扫描通过普通索引定位到聚簇索引的值,然后第二次扫描通过聚簇索引的值定位到要查找的行记录数据(回表)。非主键索引的查询需要多扫描一棵索引树,因此需要尽量使用主键索引查询。
例子:
当sql语句的所求查询字段(select列)和查询条件字段(where子句)全都包含在一个索引中(复合索引),可以直接使用索引查询而不需要回表。这就是覆盖索引。
注意复合索引引出来最左匹配原则
十六. 范式和反范式的区别?
范式优点:(第二范式)去除冗余数据;(第三范式)解决数据添加、删除问题。
范式缺点:查询时需要更多的关联,可能引起索引策略无效。例如,范式化可能将列存放在不同的表中,而这些列如果在一个表中本可以属于同一个索引。
反范式优点:所有的数据可以在一张表上显示,可以避免关联,可以设计有效的索引。
反范式缺点:肯定是范式的优点
十七.limit分页
select * from table limit (start-1)*pageSize,pageSize(start是传进来的页码,limit index,num)
一. synchronized和lock?
补充:
二. synchronized做了哪些优化(jdk1.6)?
新增的Java对象头(锁信息的标志位)实现了锁升级功能。Synchronized 同步锁初始为偏向锁,随着线程竞争越来越激烈,偏向锁升级到轻量级锁,最终升级到重量级锁。
偏向锁:主要用来优化同一线程多次申请同一个锁的竞争,也就是现在的Synchronized锁实际已经拥有了可重入锁的功能。在我们的应用中,可能大部分时间是同一个线程竞争锁资源(比如单线程操作一个线程安全的容器),如果这个线程每次都要获取锁和释放锁,那么就在不断的从内核态与用户态之间切换。那么有了偏向锁,当一个线程再次访问这个同步代码或方法时,该线程只需去对象头中去判断一下是否当前线程是否持有该偏向锁就可以了。
轻量级锁:当有另外一个线程竞争获取这个锁时,由于该锁已经是偏向锁,当发现对象头中的线程 ID 不是自己的线程 ID,就会进行 CAS(compare and swap, 操作系统的TSL)操作获取锁,如果获取成功,直接替换对象头中的线程 ID 为自己的 ID,该锁会保持偏向锁状态;如果获取锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁。轻量级锁适用于线程交替执行同步块的场景,绝大部分的锁在整个同步周期内都不存在长时间的竞争。用的是CAS乐观锁(自旋锁)
重量级锁:操作系统的pthread_mutex
补充:
CAS, compare and swap?
为什么要自旋锁?
自旋锁相当于Busy wating,并不放弃cpu,而是一直测一直测有没有资源,yield the CPU;
互斥锁相当于Sleep and Wakeup,把自己阻塞了,等待cpu重新调度(锁的东西相当于资源,从running进入blocking,当满足锁释放条件了再从blocking到ready,等待cpu调度)
在线程竞争不激烈时,用自旋锁,因为需要busy waiting的时间比较少。且减少了用互斥锁用户态内核态切换的开销。
在线程竞争激烈时,用互斥所,因为busy waiting时间较长,浪费了CPU资源.
什么是内核态?什么是用户态?为什么切换开销大?
二.Volatile关键字?
不使用副本,直接操作原始变量(直接操作这块内存),相当于节约了拷贝副本,重新放回的步骤。(主要在attribute上使用)
在正常进行变量处理三个步骤:
获取变量原有数据内容副本;
利用副本为变量进行数学计算;
将计算后的变量,保存到原始空间之中;
通过以上,可以保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。但是,volatile关键字能保证可见性没有错,但是上面的程序错在没能保证原子性。
禁止进行指令重排序。即volatile变量的相关的语句执行,一定保证在前面的代码和后面的代码中间。内存屏障。
三.线程池及线程池参数
线程池在并发情况下用。线程池七大参数:
ExecutorService接口是java内置的线程池接口(不过在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors中提供的3个常用静态方法来创建线程池。
从它们的具体实现来看,它们实际上也是调用了ThreadPoolExecutor,只不过参数都已配置好了。 除此之外ScheduledExecutorService接口接收Executors提供的Scheduled线程池方法,可以控制线程执行时间。 除此之外,java中future接口就是专门用于描述异步计算结果的(带返回值的)。
补充:
调用方法 execute 向线程池提交任务时,以下操作:
核心线程满了,接下来进队列,队列也满了,创建新线程,直到达到最大线程数,之后再超出,会进入拒绝rejectedExecution
默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0
在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中
拒绝策略有四种:
关闭线程池
可以通过调用线程池的方法== shutdown或 shutdownNow关闭线程池。这两个方法的原理是遍历线程池中的工作线程,对每个工作线程调用 interrupt 方法中断线程==,无法响应中断的任务可能永远无法终止。
四.sleep()和wait()?
五. final、finally、finalize?
六. finally什么情况不被执行?
七. HashMap重写 hashcode 和 equals 方法?
八. HashMap版本区别?头插尾插?
jdk1.7中采用头插入法,在扩容时会改变链表中元素原本的顺序,以至于在并发场景下导致链表成环的问题。而在jdk1.8中采用尾插入法,在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了。
(jdk1.8的CourrentHashMap从分段锁变回了cas+synchronized,synchronized也做了升级)
九. Map 中,键能否重复?如果重复,会有什么现象?
Map 中不允许键重复,因为每个键对应一个值,如果有重复的键,则会出现一个键对应多个值的情况,这违背了映射的定义。但是从调用put方法角度,会覆盖之前的值。
九补. HashMap和HashTable?
九再补. map的put步骤以及map节点?
map再put一组key和value时,创建一个entry,放在数组中去。entry包含四个属性,key value hash next(引用)
map的put步骤:
1.put一个元素时,判断数组是否为空,为空则创建
2.根据key算hash值
3.通过hash值找bucket的index,如果entry != null,用equals找这条链表上的相等的值,没有的话就头插
4.如果entry == null,就直接添加元素
十.Hashmap扩容为什么都是2倍扩容?
总结:hashmap底层计算存储位置用了与运算,只有容量为2的幂次方,才能使充分散列,避免哈希冲突。所以一直保持两倍扩容
因为Hashmap计算存储位置时,使用了(n - 1) & hash。只有当容量n为2的幂次方,n-1的二进制会全为1,位运算时可以充分散列,避免不必要的哈希冲突,所以扩容必须2倍就是为了维持容量始终为2的幂次方。
十. HashSet 和 TreeSet 的区别有哪些?
十一. 锁的可重入性
一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁,请求将会成功。
lock和synchronized一样都有可重入性:在一个线程调用synchronized方法的同时在其方法体内部调用该对象另一个synchronized方法,也就是说一个线程得到一个对象锁后再次请求该对象锁,是允许的。这就是synchronized的可重入性。(需要特别注意另外一种情况,当子类继承父类时,子类也是可以通过可重入锁调用父类的同步方法)。原理是:同一个线程每进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。
十二. yield()?join()?
十三. threadlocal?
线程局部变量:用域是当前单个线程,在线程开始时分配,线程结束时回收。
在TreadLocal中有一个静态内部类ThreadLocalMap,他的get():首先获取到当前的线程t,再根据t获取ThreadLocalMap,再根据map以ThreadLocal为键取值;他的put()先取到当前的线程t,再根据t获取ThreadLocalMap,再根据map以ThreadLocal为键设值
十四. 强引用?软引用?弱引用?虚引用?
十五. 单例模式一般用在哪?
资源共享的一些情况。比如日志应用、网站的计数器、windows回收站、spring的bean。
十六. AQS?
AbstractQueuedSynchronizer,AQS内部是使用了双向链表将等待线程链接起来。
十七. String常量池
public class Demo {
public static void main(String[] args) {
String str1="abc";
String str2="abc";
String str3=new String("abc");
String str4=new String("abc");
String str5=str4.intern();
System.out.println(str1==str2);//第一行,true
System.out.println(str1==str3);//第二行,false
System.out.println(str1==str5);//第三行,true
System.out.println(str3==str4);//第四行,false
System.out.println(str3==str5);//第五行,false
System.out.println(str1.equals(str2));//第六行,true
System.out.println(str1.equals(str3));//第七行,true
System.out.println(str1.equals(str5));//第八行,true
System.out.println(str3.equals(str4));//第九行,true
System.out.println(str3.equals(str5));//第十行,true
}
}
问题:String str1=“abc”;String str3=new String(“abc”);两个语句分别创建了几个对象?对象存储位置?s1和s2相等吗?执行顺序是先第一条再是第二条创建几个对象?
第一个语句一个,第二个语句一个或两个。
第一个语句存在常量池,第二个存在堆(若常量池没有,还会在常量池创建一个)。
(==)不相等,(equals())相等。
先第一条再是第二条的话,一共两个。
补充问题:String str = “ab” + “c”;创建了几个对象?
三个,“ab” , “c” , “abc” 。若之前有某一个了,就俩呗。
十八. interface和abstract的区别?
interface一般是去定义规范or解耦用的,具体用法是implements这个接口;abstract一般是抽象类,比如说苹果和鸭梨都是水果这种共同的属性,具体用法是extends这个父类;(c++里也有这个,但java里的abstract不支持多继承,interface支持多继承(实现))
抽象类可以有构造方法,接口中不能有构造方法。
抽象类中可以有成员变量,接口中没有成员变量。
抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的。
十九. abstract类里一定要有抽象方法吗?
抽象类不一定有抽象方法;但是包含一个抽象方法的类一定是抽象类。(可能是继承父类的成员变量用吧)
二十. interface可以写方法的实现吗?
可以。jdk1.8后,可以在interface中写实现方法,前提是需要被default或static关键字所修饰。(当就算写实现方法也支持Override重写)
二十一. JRE 和 JDK 的区别是什么?
JRE: Java Runtime Environment。JDK:Java Development Kit。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具,还包含了java程序编写所需的文档和demo例子程序。如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。
二十二. hashmap为什么不一开始用红黑树?
Because TreeNodes are about twice the size of regular nodes。只有当链表长度大于8时,才转换成红黑树来提高查询的效率。而当长度降到 6 就转换回去,这体现了时间和空间平衡的思想。同时红黑树插入和删除操作也需要耗时。
二十三. hashmap什么时候扩容?负载因子为什么0.75?
当HashMap中元素总个数达到阈值(bucket * 负载因子(一般为0.75)a时就会扩容2倍。
冲突的机会与空间利用率之间寻找一种平衡与折衷。0.75让其满足泊松分布(桶中元素到达8个的时候,概率已经变得非常小,也就是说用0.75作为加载因子,每个碰撞位置的链表长度超过8个是几乎不可能的。)
二十四. 死锁?
可抢占资源、不可抢占资源(eg. 打印机)
死锁的四个条件:
解决死锁(忽略、检测、避免、预防)
具体场景下解决死锁:
解决循环等待: 线程t1先获取资源A然后获取资源B,而线程t2先获取资源B再获取资源A,这就导致了死锁。
控制加锁顺序:此场景下,我们可以让线程t2和线程t1 保持一致就可以解决死锁问题。
二十五. 线程安全的List
二十六.问linux的时候提这俩java的
二十七.什么语言使用了引用计数法?
脚本语言。Python、PHP
指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。
二十八.泛型擦除
比如在集合中都是List,擦出了< T >
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
打印的结果为 true 是因为 List< String >和 List< Integer >在 jvm 中的 Class 都是 List.class。
这是因为,泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
二十九.lambda表达式
()->{}。priorityqueue做排序,比如我们想倒序,正常是implements Comparator时,要覆写comapre方法,有lambda表达式后直接(x1,x2)->{return x2-x1;}
三十.Stream api
函数式编程,给容器加强聚合操作。我理解是整了一种流操作
容器.parallelStream().filter(过滤).sorted(排序).collect(收集还原成list)
三十一.基本数据类型
byte short char int long float double boolean
三十二.jvm调优
jmap、jstat查看堆内存信息
jstack看函数调用栈,检查死锁
Xms是初始堆的大小,Xmx堆的最大值,XX:SurvivorRatio,新生代中eden区和两个survivor的比例。
三十三.java中的异常有哪些
exception
空指针异常类:NullPointerException
输入输出异常:IOException
找不到类:java.lang.ClassNotFoundException
error
堆内存满:java.lang.OutOfMemoryError
迭代栈溢出:java.lang.StackOverflowError
三十四.collections和collection
Collections是工具类,如sort。Collection是集合的顶级接口,比如set和list的父接口就是它
一. 类加载过程,分几步?
加载、验证、准备、解析、初始化
1.补充一个为什么单例懒汉式必须加volatile关键字:
double check后,instance = new SingletonClass()这条语句,并不是一个原子操作,在JVM中其实是3个操作:
在JVM中的及时编译存在指令重排序的优化,也就是说不能保证1,2,3执行的顺序。如果是 1-3-2,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。volatile可以保证1、2、3的执行顺序。
2.补充一个static和final赋值阶段
stiact属性:
在准备阶段,为类的静态变量(static)分配内存并设置初始值。
在初始化阶段,对static变量赋值,执行静态代码块。
final属性:
final修饰的实例属性,在实例创建的时候才会赋值。
static+final属性:
JVM规范是在初始化阶段赋值,但是HotSpot VM直接在准备阶段就赋值了
二. 类初始化的过程
原则:先静态
原则:先父后子
原则:先属性、再构造、再方法
父类的静态代码块(包括静态属性)
子类的静态代码块(包括静态属性)
初始化父类的属性值
父类的构造方法
父类的普通方法
初始化子类的属性值
子类的构造方法
子类的普通方法
三. JVM分成哪几部分?方法区放的什么?
类加载器、运行时数据区、字节码执行引擎
已被虚拟机加载的类的信息、常量、静态变量等
四. OOM内存泄露,出现原因,解决方法?(memory leak 最终会导致 out of memory)
出现原因:
五. 说一下JMM(java memory model)?
一. Spring和Springboot区别?
二. AOP?IoC?
实现:类实现aop,比如这个log类,需要如implements MethodBeforeAdvice(也有之后,也有环绕)。并覆写方法。
然后在.xml文件中配置这个bean,并设置
(当然也可以不这样implements MethodBeforeAdvice,可以自定义类orLog类加注解实现aop,相应的配置文件也不一样了,注解实现的xml配置最简单)
下面是注解实现aop
三. Instantiation bean 实例化bean的方式?
Instantiation with a Constructor(项目中entity那种最普通的)
Instantiation with a Static Factory Method(自己写一个工厂单例类,并用单例返回)
Instantiation by Using an Instance Factory Method(factory本身作为bean,然后这样可以自己写工厂下多个返回单例方法)
四. Spring依赖注入(dependency injection)方式?
(首先,依赖注入是另一个角度的控制反转。)
依赖:bean对象创建依赖于容器,bean对象的依赖资源(property给的字符串)等等
注入:bean对象依赖的资源由容器来设置和装配
(spring的docs中间还有两条对属性或引用的设置的解释)
ApplicationContext是用来管理bean对象的。(如我们项目中的applicationContext.xml)。通过配置beans.xml(or applicationContext.xml)的property属性传值。然后bean这个类就会通过set方法注入这个值。(注意,属性property配置的是set方法的名字去掉set这三个字符,所以要命名规范!)
五. bean在什么时候被创建?
Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created.
默认Spring容器创建时就创建了bean
Otherwise, the bean is created only when it is requested.
否则,只有在被请求时才创建
六. Spring循环依赖的解决方式?
产生原因:
If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.
如果主要使用构造函数注入,则有可能创建不可解决的循环依赖场景。
解决方案:
One possible solution is to edit the source code of some classes to be configured by setters rather than constructors.
使用setter注入而不是构造器注入
七. Spring如何装载bean?
九. MVC?
Model View Controller, 使用MVC是将M和V实现代码分离,从而使同一个程序可以使用不同的表现形式。最重要的一点是多个视图能共享一个模型(解耦,可重用)
十. 静态代理?动态代理(与AOP联合说)?
References:https://www.zhihu.com/question/40536038/answer/685995295
public interface Programmer {
// 程序员每天都写代码
void coding();
}
public class Java3y implements Programmer {
@Override
public void coding() {
System.out.println("Java3y最新文章:......给女朋友讲解什么是代理模式.......");
}
}
public class ProgrammerBigV implements Programmer {
// 代理类
// 指定程序员大V要让谁发文章(先发文章、后点赞)
private Java3y java3y ;
public ProgrammerBigV(Java3y java3y) {
this.java3y = java3y;
}
// 程序员大V点赞评论收藏转发
public void upvote() {
System.out.println("程序员大V点赞评论收藏转发!");
}
@Override
public void coding() {
// 让Java3y发文章
java3y.coding();
// 程序员大V点赞评论收藏转发!
upvote();
}
//......
// 若有更多其他需要的功能,还需要Override多个方法,比如reading()、delete()里也要upvote()这个业务
}
public class Main {
public static void main(String[] args) {
// 想要发达的Java3y
Java3y java3y = new Java3y();
// 受委托程序员大V
Programmer programmer = new ProgrammerBigV(java3y);
// 受委托程序员大V让Java3y发文章,大V(自己)来点赞
programmer.coding();
}
}
动态代理的代理类是动态生成的。静态代理的代理类是提前写好的。
动态代理的好处:对于同一种业务,不需要Override各种方法,只需要在invoke里把我们的公共业务放进去(当然了不同的业务肯定要写不同的动态代理)
基于接口动态代理----jdk动态代理(Spring的AOP帮我们封装了动态代理)
javassist
Proxy类和InvocationHandler接口
十一.@Resources和@Autowired?
遇上两个bean的class相同,但是配置信息不同,那么怎么区分这两个bean呢???注入时注入的是哪个呢?这就可以利用@Resource了。把两个Bean取名不同,一个叫simpleTairConfig,一个叫simpleTair,这样在注入时通过@Resource(name = “simpleTairConfig”)
十二. spring事务、事务的传播属性
常见的事务传播属性(7种):
一. HTTP(80)和HTTPS(443)?
HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。就是在HTTP和TCP之间套了一层。
HTTPS 协议的主要功能基本都依赖于== TLS/SSL 协议==,TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
二. 服务器保持了大量TIME_WAIT状态?
产生原因:TIME_WAIT是主动关闭连接的一方保持的状态,对于爬虫服务器来说他本身就是“客户端”,在完成一个爬取任务之后,他就会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。(即四次挥手中,服务器端也可以主动发起FIN=1)。
在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。持续的到达一定量的高并发短连接,会使服务器因端口资源不足而拒绝为一部分客户服务。
解决方法:让服务器能够快速回收和重用那些TIME_WAIT的资源。编辑内核文件/etc/sysctl.conf。开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接。开启 TCP连接中TIME-WAIT sockets的快速回收。
三. 短连接与长连接?
短连接一般只会在client/server间传递一次读写操作,即一次完事儿后就close关闭了。长连接client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接(在一个TCP连接上可以传送多个HTTP请求和响应,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点)。(HTTP/1.0默认非持久连接,如果想要在旧版本的 HTTP 协议上维持持久连接,设置Keep-Alive,相当于长连接了)。
四. HTTP1.0 HTTP1.1 HTTP2.0?HTTP/3了解吗?
HTTP1.0与HTTP1.1区别:4个
HTTP2.0与HTTP1.x区别:
HTTP/3 是在 QUIC(Quick UDP Internet Connections) 基础上发展起来的,其底层使用UDP进行数据传输,上层仍然使用 HTTP/2。
五. url从输入到回车?
六. get请求和post请求
七. 除了post和get还了解哪些http请求方法?
connect请求:connect请求告诉代理你要和哪个服务建立连接,代理给你返回200以后,你后续发送的所有流量才会被代理转发给你本来想要访问的服务器。(将服务器作为代理,让服务器代替用户进行访问。)
八. TCP 是如何保证可靠性的?
九. HTTP 是不保存状态的协议,如何保存用户状态?
HTTP 服务器并不保存关于客户机的任何信息,所以我们说 HTTP 是一个无状态协议。
优点:安全性高,因为状态信息保存在服务器端。
缺点:由于大型网站往往采用的是分布式服务器,浏览器发送的 HTTP 请求一般要先通过负载均衡器才能到达具体的后台服务器,倘若同一个浏览器两次 HTTP 请求分别落在不同的服务器上时,基于 Session 的方法就不能实现会话保持了。解决方法:采用中间件,例如 Redis,我们通过将 Session 的信息存储在 Redis 中,使得每个服务器都可以访问到之前的状态信息。
优点:服务器不用保存状态信息, 减轻服务器存储压力,同时便于服务端做水平拓展。
缺点:该方式不够安全,因为状态信息存储在客户端,这意味着不能在会话中保存机密数据。除此之外,浏览器每次发起 HTTP 请求时都需要发送额外的 Cookie 到服务器端,会占用更多带宽。
十. DNS 的作用和原理?
DNS将域名解析为ip地址。
客户端(主机)把DNS查询报文发给代理商的本地DNS服务器,本地 DNS 服务器将该报文转发到根 DNS 服务器,根 DNS 服务器注意到查询的 IP 地址后缀为 edu 后向本地 DNS 服务器返回负责 edu 的顶级域名服务器的 IP 地址列表,该本地 DNS 服务器则再次向这些== 顶级域名服务器发送查询报文==,该顶级域名服务器注意到 mn.edu 的前缀,并用权威域名服务器的 IP 地址进行响应。最后找到了负责 def.mn.edu 的权威 DNS 服务器。
十一. DNS用的什么传输协议?
DNS = UDP + 53 or TCP + 53
十二. URL(即统一资源定位符, Uniform Resource Locator)和URI
URI:定义资源是什么
URL:定义资源是什么,以及如何获取
十三. 状态码?
1XX:指示信息–表示请求正在处理
2XX:成功–表示请求已被成功处理完毕
3XX:重定向–要完成的请求需要进行附加操作
4XX:客户端错误–请求有语法错误或者请求无法实现,服务器无法处理请求
5XX:服务器端错误–服务器处理请求出现错误
十四. 状态码 301 和 302 的区别?
301 永久重定向,30(2|3|7)临时重定向,语义和实现有略微区别;
十五. HTTP 异常状态码知道哪些?
十六.TCP如何保证有序
seq和小ack序列号保证(脑子里面想那幅图)
十七.TCP为什么四次挥手?为什么不是3次?
tcp是全双工通信,服务端和客服端都能发送和接收数据。tcp在断开连接时,需要服务端和客服端都确定对方将不再发送数据。(脑子里想那副图)
在客服端第1次挥手时,服务端可能还在发送数据。所以第2次挥手和第3次挥手不能合并。(和上面有联系)
十八. 为啥用udp?
TCP适合实时性要求不高,但要求内容要完整传输的应用。相比而言,UDP由于无连接、无重传确认,所以传输效率高、延时小,适合实时性要求高的应用
十九.udp如何实现可靠性传输?
tcp的可靠传输是在传输层实现的。udp可以在应用层实现可靠传输,把ack的确认机制、流量控制、拥塞控制、窗口设置等设置在传输层。
一.详细聊聊进程和线程的区别?
进程,资源分配的最小单位
线程,调度的最小单位
进程的粒度大,体现在创建进程和上下文切换开销。线程粒度小,在创建线程和上下文切换开销都较小。(进程资源最小单位,PCB、资源空间都大;同时这样也体现了上下文切换时候寄存器保护现场的内容)
linux进程之间通信用的方法和线程之间同步用的不一样。
进程中有一个或多个线程,是个包含关系。
二.线程的地址空间?
不太了解。知道线程栈这回事。
三.内存管理
一. Java 5亿整数大文件怎么排序?
1.分:按内存可承担的大小,将大文件分成一个一个的小文件,读入内存,在内存对该小文件进行排序,排序后放到磁盘。
2.和:外排序我们可以将这个“二”扩大到M。(内排序的归并排序是采用二路归并)。选择每个文件的第一个数读入内存(已经排序),找到min,写出磁盘。注意下一次选min需要先把写出的这个补齐了(所以要记录文件的索引,fd?)。
二. 排序算法?
冒泡排序:O(n2):基本有序情况下,冒泡最好,可以接近O(n)
简单选择排序:O(n2)
直接插入排序:O(n2)
希尔排序:O(nlogn)~O(n2)
堆排序:O(nlogn):最坏情况下,还能保证O(nlogn)
快速排序:O(nlogn):经过优化的快排,是最好的
归并排序:O(nlogn):最坏情况下,归并最好,还能保证O(nlogn),且稳定
文中图片参考了B站视频、阿里开发者学院视频、其他知乎和CSDN博客等