面试基本知识总结

一、基础篇
1.集合中list和set的区别
答:首选list集合是有序的,可以通过角标获取,效率要高于set集合。set集合是无序的。list集合可以存储重复的值,而set集合不允许存储重复的值
list:arrayList 数据结构是数组,存储的是连续的内存,有利于查找。
linkedlist:链表结构,可以存储在不连续的片段,有利于增加和删除
vector也是数组,是线程安全的,比较慢。
当常见一个集合对象时,默认是0,只有在放入第一个元素的时候创建10个。当满时按照1.5倍去扩容。扩容后将原数组copyof方法复制过来。
set: hashset linkedhashset treeset hashset底层是hash值,底层是由hashmap实现的。
Map:hashmap 底层是数组和链表,也叫hash链表,默认是16,负载因子是0.75,当链表的个数大于8时变成红黑树,提高速度,遍历时有三种方法 map.keyset(),map.entrySet(),map.entryset.iterator()
concurrenthashmap 线程安全 分段加锁,速度会比hashtable快。
红黑树的规则:根节点是黑色,每个节点不是黑色就是红色,如果节点是红色,则它的子节点必须是黑色。从根节点到叶子几点,每条路径中黑色的节点一定是相同的。
2.实现线程有几种方式,他们之间有什么区别?
答:实现线程有三种方法 1.继承thread类 2.实现runnable接口 3.通过callable 和futureTask创建线程
thread和runnable无返回值,不能抛出异常,
线程池:四种创建方式 。1-newfixedthreadpool(int nThreads) 指定线程个数
2-newCachedTreadPool()创建一个线程缓存池
3-newSingleThreadPool(),创建单个线程
4-newScheduledThreadPool(int corePoolSize)
线程的同步:两种方式synchronized 和 lock锁 区别synchronized是代码片段,lock是一个类,并且lock的解锁要通过unlock去实现。cas锁是乐观锁,加版本号的那种。
threadLocal的适用场景
1、每个ThreadLocal只能保存一个变量副本,如果想要创建一个线程能够保存多个副本以上,就需要创建多个ThreadLocal。
2、ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险。
3、适用于无状态,副本变量独立后不影响业务逻辑的高并发场景。如果业务逻辑强依赖于副本变量,则不适合用ThreadLocal解决,需要另寻解决方案。
例子,数据库的连接,每个连接开始和关闭互相不影响。
单例设计模式代码
public class Single{
private static volatile Single single = null;
private Single(){}
public static Single getInstance(){
if(singlenull){
synchronized(Single.class){
if(single
null){
single = new Single();
}
return single;
}
}
}
}
3.IO流
IO详细介绍
io流和nio流的区别:
io是面向流的,nio是面向缓冲的,io是阻塞的,也就是说一个线程在用来写或者读的时候,这个时候写线程或者读的时候是阻塞的,那么就要等待,直到空出来为止。而nio不是这样的,当一个线程读取数据的时候,没有数据,他不是在等待,而是可以干其他的事情,直到有数据再继续。
4.理解jvm
jvm的组成,程序计数器,本地方法区,方法区,堆,和栈。其中堆和方法区是线程公有的,其他三个是线程私有的。
堆又分为年轻代,老年代和持久代
年轻代分为eden(伊甸园区),surviour(from space和to space),一般情况下jvm的内存最大值和最小值设置成一样大小,避免垃圾回收后内存重新分配,再计算会耗时。
大部分对象的创建都存在eden区,当eden区满时会将还存活的对象复制到存活区中的from区,当存活区from对象满时,将存活的对象在复制到to区 ,这样往返当to区满时,会将存活的对象复制给老年代。年老区的对象一般都是经历过n次垃圾回收后仍然存活的对象,一般我们认为存储的都是生命周期比较长的对象。
持久代存放的一般是静态文件,如java类和方法等。scavenge gc伊甸园区的回收
Full Gc整个堆的回收,jvm的调优过程很大程度都是在对full gc的调优。一般调用fullgc的时机为,年老区被写满,持久区被写满,或者是调用System.gc().
设置年轻代为2G,年老代为64m,垃圾回收时年老代设置为并发,年轻代设置为并行 。
5.jdbc连接
1.获取数据库驱动-driver
2.创建连接
3.获取执行sql语句
4.执行sqll
5.获取返回值
6.关闭资源
preparestatement和statement的区别 prestatement是预编译的当编译一次后如果再执行就不在编译,提高效率而且可以防止sql注入。
6.数据库事务的特点,隔离级别
ACID 原子性,一致性,隔离性和持久性
事务的隔离级别有四种
读未提交 read uncommitted (此时会出现脏读,不可重复读和幻读)顾名思义读到没有提交的事务。比如事务A添加一条新的数据,但是这时候并没有提交,来了一个事务B进行查询,此时B查询出来的事务就包括了没有提交事务的A,出现脏读。
读已提交 read committed (此时出现不可重复读和幻读) 顾名思义只能读到已提交的事务。比如A事务查询数据库有一条数据中的名称是张三,此时来了一个事务B把张三 改成了李四,这时候事务A再去查找的时候就是李四,此时就造成了不可重复读。
可重复读 repeated read (存在的问题是幻读) 例如事务A查询数据库中存在的条数,此时来了一个事务B insert一条记录,事务A再次查询的时候就是比之前多了一条,此种现象就是幻读。他也是mysql数据库默认的隔离级别。
serializable 可串行化,它可以解决所有的问题,但是他的速度是极其慢的,所以一般不用。
mysql数据库默认的是可重复度,但是也是不会出现幻读的,有快照snapshot 和gopluck等来阻止幻读。
7.mysql数据库 oracle数据库
mysql数据库默认的隔离级别是repeated read 不会有幻读的情况,因为它自身弄了一个快照或者是gop锁。
mysql的常用引擎 myism 和innoDB 区别,myism没有事务,非聚集索引。innoDB有事务,聚集索引。myism适合查询比较多的。一般都是用innodb的。
聚集索引是指数据和索引在一个文件中,而非聚集索引是指数据和索引是分属在两个文件中。
索引的底层是b+tree,为什要用b+tree而不用btree呢,因为b+tree一个父节点可以有多个子节点,相同节点数b+tree会比btree的层级少,查询速度快,所以用b+tree。
数据库索引的注意事项,模糊查询%开始就有的失效,not in is not null不走索引,!= ,<>,类型转换,函数不走索引。
mysql数据采用最左原则。当复合索引时,是按照最左执行的。abc索引,其实创建的是 a 索引 ab索引 abc索引。当有bc条件是不走索引,ac时a走索引c不走索引。
数据库语句的优化 慢查询
1.开启数据库的慢查询 show_query_log
2.分析慢查询日志,explain关键字可以模拟优化器执行sql语句
3.慢查询可以优化的点,索引是否失效,优化表结构,分解关联查询等。
数据库的乐观锁与悲观锁
乐观锁,是首先认为所有数据库的操作都是没有冲突的,实现乐观锁有三种方法,一种是加版本号进行控制,一种是通过时间戳,或者是通过数据的某种状态。在更新数据的时候,where条件判断是否与查出来的数据是相同的,相同更新成功,不相同没有执行更新语句。
悲观锁 是默认所有的语句都会有冲突,添加for update 或者for update nowait进行加锁。实现锁机制首先是将自动提交关闭,因为数据库的提交默认是自动提交的。
mysql数据库的行锁和table 当有明确的id的时候,使用行锁,不明确时就是table锁,当没有查询到数据时无锁。索引也是,当索引有时,行锁,没有数据时无锁。
oracle和mysql的区别,mysql是开源的,适合互联网的产品。分页是limit,主键自增。 oracle是要花钱的,且价格高。rownum<没有大于号。实现自增要创建序列sequence。
如何删除掉数据库中重复的数据,且保留一条记录
group by having重复的数据
delete *
from A
where id in(分组 别名) and not in( min(id) 分组 别名);不起别名会报错。
8.反射的实现 .class class.forname getclass 实际应用是短信的发送,和数据的映射。
二。框架篇
1。spring的管理
spring的原理
spring事务的传播机制 有七中
1)required 支持当前事务 当A方法使用事务,B方法可以直接使用
当A方法没有事务,b创建新的事务。这是spring默认的传播机制。
2)support 支持当前事务 当A方法使用事务,B方法可以直接使用
当A方法没有事务,B方法以非事务执行。
3)mandatory 支持当前事务,A方法有事务,B方法直接使用
当A没有事务时,B抛出异常。
4)required_new A方法有事务挂起当前事务新建一个事务,没有事务,直接创建一个新的事务。
5)not_supported 不支持事务,如果有事务挂起,以非事务执行。
6)never 不支持事务,A方法有事务,B方法将抛出异常。
7)nested 嵌套事务。
spring中bean的循环注入问题
别人写的比较好解说
2。mybatis的应用
首先mybatis和hibernate(纯orm) mybatis应用简单,可以直接写sql并且可以很容易的写出高效的sql语句,一般在电商平台应用比较广泛。hibernate企业oa系统或者erp系统应用比较多。
mapper中含有的标签 if where foreach select insert update delete 关联关系,一对一 :association 和 collection
mybatis的延迟加载,默认要去配置的。
mybatis 有缓存,一级缓存针对sqlsession的 第一次会执行数据库语句但是当同样的语句在进行执行的时候不在去数据库中查找而是从缓存中取,但是一旦执行更改操作缓存失效。
二级缓存 cache,需要开启,整个space为单位,先去二级缓存中获取,没有再查但当有更新操作时,缓存清空。或者用encache来实现二级缓存。
3。spingmvc的加载过程
引入,springmvc解析
4。redis 和 memcache的区别
redis和memcache都是将数据放在内存中,只不过memcache可以缓存其他东西,例如图片和视频等
redis支持许多数据类型,string, set,hash,zse,list等
redis可以将不频繁使用的数据存放到磁盘中
过期策略 memcache set时就指定,redis可以通过expire
memcache挂掉后数据没有了,而redis可以定期持久化
memcahce不可以恢复数据,redis可以通过快照和aof日志恢复数据。
5。springboot的启动过程
别人的比较好的说明
6。restful
restful风格的作用
7。父类子类静态代码段,非静态代码块和构造函数和方法的执行顺序。a、 b extends a
测试new B() 父静态代码块 子静态代码块 父非静态方法 父构造方法 子非静态方法 子构造函数 方法的执行需要调用。
当B.静态方法时 再创建b对象 执行为父静态代码块,子静态代码块 调用的方法 父类非静态代码块,父类构造函数 子类非静态代码块,子类构造方法。
8。linux常用的指令
tar cvf 压缩
tar xvf 解压
tail -f catelina.out
vim i 光标的前面 I整行的前面 a光标的后面 A 整行的后面 o在当前行的前面插入一行 O在当前行的下方插入一行。
ps -ef|grep tomcat查找指定的端口号
kill -9
9。wait和sleep的区别 wait object sleep thread sleep不释放锁,wait释放锁
10。常见的排序方式
(1)冒泡排序 时间复杂度O(n的平方)
public void bubbleSort(int[] arr) {
int temp;//定义一个临时变量
for(int i=0;i<arr.length-1;i++){//冒泡趟数
for(int j=0;j<arr.length-i-1;j++){
//如果顺序不对,则交换两个元素
if(arr[j+1]<arr[j]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
(2)对冒泡排序的改造->快速排序 时间复杂度为O(nlog2n)
//快速排序
public static void sort(int numbers[],int low,int high){
int start = low;
int end = high;
int key = numbers[low];

    while(end>start){
        //从后往前比较
        while(end > start && numbers[end] >=key)
            end--;
        if(numbers[end] <= key){
            int temp = numbers[end];
            numbers[end] = numbers[start];
            numbers[start] = temp;
        }
        //从前往后比较
        while(end>start &&numbers[start]<=key)
            start++;
        if(numbers[start]>=key){
            int temp = numbers[start];
            numbers[start] = numbers[end];
            numbers[end] = temp;
        }
    }
    
    if(start > low) sort(numbers,low,start-1);
    if(end <high) sort(numbers,end+1,high);        
}

}
单例模式的核心就是构造函数是私有的,保证不被调用,当前对象只有一个实例,节省空间,并且不会存在多个对象同事存在有不同结果的问题。
欢迎大家补充知识点,如果有写错的地方,请不吝赐教。

  • 51
    点赞
  • 220
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值