2021-03-06

JAVA

1.ArrayList和LinkedList区别

ArrayList是Array的数据结构,LinkedList是链表

前者是数组队列,后者为双向链表结构,也可当作堆栈、队列和双端队列。

Arraylist

  • 查询快(因为地址是连续的
  • 增删慢(会创建一个新的数组,该数组是原数组的长度加一,然后再把原来的数组复制过去,再把新的加进去
  • 多线程,效率高,速度快

LinkedList

  • 查询慢(查询首尾元素快
  • 增删快
  • 多线程
  • 有大量操作首尾元素的方法

2. volatile 与 synchronized 的区别

(1)仅靠volatile不能保证线程的安全性(原子性)

  • volatile只能修饰变量,而synchronized还可修饰方法
  • volatile只能保证数据的可见性,不能用来同步,因为多个线程并发volatile修饰的变量不会阻塞

synchronized不仅保证可见性,而且还保证原子性。因为只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized

实现同步

可以把需要锁起来的资源放到一个方法里,然后给那个方法加synchronized

3.HashMap和Hashtable的区别

  1. 共同点:都是双列集合,底层都是哈希算法
  2. 区别:
线程效率存储null值和null键
HashMap不安全可以
Hashtable安全不可以

Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步

4.单例设计模式(懒汉,饿汉)

懒汉

public class Lazy {
    private static volatile Lazy instance = null;
    private Lazy() {}
    public static synchronized Lazy getInstance() {
        //先判断是否存在实例,有就不new了
        if (instance == null) {
            instance = new Lazy();
        }
        return instance;
    }
}
public class Hunger {
    //创建的时候就new了
    private static Hunger instance = new Hunger();
    private Hunger(){}
    public static Hunger getInstance() {
        //直接返回事先new好的实例
        return instance;
    }
}

5.锁粗化

把很多次锁的请求合并成一个请求,以降低短时间内大量锁请求、同步、释放带来的性能损耗。

6.被final修饰的类不能被继承,被final修饰的变量不能被修改

比如String类

7.反射机制及使用场景

可以让我们在运行时获取类的信息,比如它的属性、构造器、方法、注解等。

适用于需要动态创建对象的场景。

8.内存泄漏/内存溢出

内存溢出:申请不到足够的内存

内存泄露:无法释放已申请的内存

9.动态代理和静态代理

10.Java基本类型

byte: 8位

char: 16位

boolean: 只有true false

float: 32位

long: 64

short: 16

int: 32

double: 64

11. String使用陷阱

String的值是不可变的,这就导致每次对String的操作都会生成新的String对象

img

12.Stringbuffer StringBuilder

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

StringBuilder 的方法不是线程安全的(不能同步访问),但速度快。

所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

(1)如果要操作少量的数据String

(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer

(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。

13.线程池

14. ConcurrentHashMap

锁分段技术:将数据分成一段一段存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

15.重构

通过调整程序代码改善软件的质量、性能,使程序的设计模式和架构更趋合理

16. 重写

也叫覆盖,子类继承父类,而子类中的方法与父类中的方法名、参数个数、类型都完全一致时,就称子类中的这个方法重写了父类中的方法。

17. 重载

同一个类中,多个方法名一样,参数列表不一样的情况就是方法重载。

18. JVM

  1. 栈:存放的是方法中的局部变量,方法的运行一定是在栈里
    局部变量:方法的参数,或者是方法内部的变量
    作用域:一旦超出作用域,立刻从内存中消失
  2. 堆:new出来的东西
    堆内存里面的东西都有一个地址值,16进制
    堆内存里面的数据都有默认值,规则:
    整数0
    引用null
    布尔false
    字符’\u0000’
    浮点:0.0
  3. 方法区:存储.class相关信息,包含方法的信息(叫什么?返回什么
  4. 本地方法栈(native area):与操作系统相关
  5. 寄存器(pc register):与CPU相关
    b站黑马程序员P85数组的内存图 https://www.bilibili.com/video/BV1Qy4y1k7kL?p=85&spm_id_from=pageDriver
    两个数组的内存图

数据库

B+树和B树

它们都是m叉平衡树

矮胖,层数少,可以减少磁盘IO次数

B树每个节点都存储key和data,所有节点组成这棵树,叶子节点指针为null

B+树只有叶子节点存储data,每个叶子节点增加一个指向相邻节点的指针

1.b+树相比于b树的查询优势

  1. b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
  2. b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢);
  3. 对于范围查找来说,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历,如下两图:

3.索引失效

  1. 估计使用全表扫描比使用索引快
  2. 条件中有or
  3. 复合索引,如果索引列不是复合索引的第一部分,则不使用索引
  4. 如果like是以%开始的,则该列上的索引不会被使用
  5. 如果列为字符串,则where条件中必须将字符常量值加引号,若不加引号则不会使用索引
  6. 如果使用MEMORY/HEAP表,并且where条件中不使用“=”进行索引列,那么不会用到索引,head表只有在“=”的条件下才会使用索引

6.多线程和单线程区别

多线程程序:有多个线程,线程之间独立运行,能有效避免拥塞,并提高程序的运行性能。

单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)

进程:一个正在运行的程序可以看作一个进程

线程:程序中独立运行的代码段

一个进程是由一或多个线程组成,进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。

7.多线程单线程通信

  • 管道通信
  • 命名管道
  • 消息队列
  • 共享存储
  • 信号量
  • 套接字
  • 信号

操作系统

1.死锁

11个同类资源被N个进程共享,每个进程最多可以请求多3个资源才能保证系统不会发生死锁。

N*(3-1)+1=11,得N=5

网络

1.百度搜索发送什么,从osi七层模型解释

要发送的这份数据首先经过了应用层,应用提供了用户接口,

其次经过表示层,数据经过了加密,压缩以及数据描述,使得应用程序不必担心在各台主机中表示/存储的内部格式不同的问题。

经过会话层建立会话,如session认证、断点续传。

接下来进入运输层,把进程口封装数据包,这样才知道数据是当前电脑哪个进程发送的数据报

然后是进入网络层,通过ip地址找到服务器所在位置并进行相连

之后进入数据链路层,将ip数据包封装成帧

最后进入物理层,进行数据帧转换成比特流0或1,通过硬件进行传输。

2.TCP三次握手四次握手

三次握手

在这里插入图片描述

为什么要三次握手?

为了防止已失效的连接请求报文段突然又传送到了服务端,占用服务器资源。

四次挥手

在这里插入图片描述

为什么要四次挥手

客户端发送了FIN连接释放报文之后,服务器收到了这个报文后,就会进入COLSE-WAIT状态,然后继续发送还未发完的数据。待数据传送完后,就会发送FIN=1,释放连接。

2MSL 报文最大生存时间/TIME-WAIT

  • 确保最后一个确认报文段能够到达,如果服务端没有收到这个报文,他会再发一遍FIN报文,这样客户端会重发
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文段都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文段。

3.TCP为什么是可靠传输?

https://blog.csdn.net/qq_41431406/article/details/97926927

TCP通过校验和、重传控制、序号标识、滑动窗口、确认应答。

  1. 三次握手建立连接

    1. SYN seq
    2. SYN seq ACK
    3. ACK
  2. 传输数据

    1. ACK机制

      1. 确认应答
        1. seq=x
        2. ack = x+1
        3. seq = x+1
        4. ack = x+2
      2. 当发送错误的时候,会发生:
        1. 超时重传机制(发送方):当发送方发完报文后,在计时范围内,若没有收到相应的ACK确认报文,那么发送方就会重传报文。
        2. 快速重传机制(接收方):发送方会一直发送,不会等接收方的ack报文。接收方一旦收到序列号不对的报文,就会发送三个连续的ACK标志,告诉发送方在传输过程中出现了丢包。发送方收到这三个报文后,就会立刻补发。
    2. 流量控制(滑动窗口):发送方维持

      1. 让发送方的发送速率不要太快,让接收方来得及接受。发送方的发送窗口不能超过接收方给出的接收窗口的数值。
      2. TCP的窗口单位是字节,不是报文段
      3. 四类:
        1. 已发送已确认
        2. 已发送未确认
        3. 未发送但允许发送
        4. 还没发送但窗口满了不允许发送
      4. 停等协议:发送窗口=1,接受窗口=1;每个发送报文都要等到被确认后才能再次发送。
      5. 后退n步协议:发送>1,接收=1;如果某个报文丢失,那么将要重新发送这个丢失报文及以后的所有报文(包括已经发送的)
      6. 选择重传:发送>1,接收>1;如果某个报文丢失,那么将要重新发送丢失的报文就行。
    3. 拥塞控制:考虑整个网络

      1. 拥塞窗口cwnd/ 拥塞阈值ssthreshold

        发送窗口小于或等于拥塞窗口发送方控制拥塞窗口的原则是只要网络没有出现拥塞,拥塞窗口就增大一些,以便把更多的分组发送出去。但是只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络的分组数。

      2. 策略:

        1. 慢启动(<;cwnd呈指数增长
        2. 拥塞避免(>;cwnd呈线性增长
        3. 拥塞解决(解决方法是拥塞阈值乘性减即ssthreshold=cwnd/2,cwnd=1,或者ssthreshold=cwnd/2,cwnd=ssthreshold
        4. 快速恢复:超时重传——>慢启动 ;快速重传——>拥塞避免阶段

4.TCP和UDP的区别

通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响。

TCPUDP
面向连接无连接
可靠不可靠
效率低一点实时性较好
点到点n对n(1~n)
系统资源要求较多系统资源要求较少

JVM

1. java8虚拟机和之前的变化更新?

2.什么是OOM?

3.什么是栈溢出?怎么分析?

6. 谈谈JVM中类加载器你的认识?

7.堆和栈

存储:main()、基本类型变量(byte, float, boolean, long, short, int, double,char)、引用类型变量、方法函数

栈的优势:存取速度比堆快,仅次于寄存器,栈数据可以共享

缺点:存在栈中的数据大小和生存期必须是确定的,缺乏灵活性

存储 :由new创建的对象和数组

在堆中分配的内存,由jvm自动垃圾回收器来管理。

数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

8. JVM内存模型和分区

9.堆里面的分区有哪些

10. 年轻代的GC算法:

复制-清除

  1. 在GC开始的时候,对象只会存在Eden区和survivor区的from区,to是空的.

  2. 紧接着进行GC,Eden区中所有存活的对象都会被复制到"TO",而"from"区中,仍存活的对象会根据他们的年龄来决定去向,年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)会被移动到老年区,没有达到阈值的对象会被复制到“To”区域。

  3. 经过这次GC,Eden和from区已经被清空. 此时from to会交换它们的角色,以确保to是空的.

  4. minor GC会一直重复这样的过程,直到to区被填满,一旦to区被填满,会将所有对象移动到年老代中。

1个Eden区和2个Survivor区(分别叫from和to)。默认比例为eden:from:to = 8:1:1

好处:没有内存碎片

坏处:浪费了内存空间,(to区是空的

最佳使用场景:对象存活度较低的时候,即新生区

11.标记-清除算法

扫描对象,标记,对没有标记的对象进行清除

好处:不需要额外的空间

坏处:两次扫描,浪费时间,会产生内存碎片
在这里插入图片描述

12.标记-整理算法

防止内存碎片的产生,再次扫描,向一端移动存活的对象,多了一个移动成本

优化:多次清除,再做整理

GC算法总结

效率:复制>标记清除>标记压缩

内存整齐度:复制=压缩>清除

内存利用率:压缩=清除

排序

数据结构

线性结构:线性表、栈、队列、串、数组

非线性结构:图、树

数据运算:插入、删除、修改、查找、排序

物理存储结构:顺序结构、链式结构

项目

(头像如何获取的,怎么传给后端?数据库如何设计的?有几张表、包括哪些属性?web页面在什么时候初始化建立数据库的连接?如何判断数据库中已经有添加的菜名?项目有什么难点?)

项目的登录逻辑、设置token的过期时间、如果token被拦截伪造登录了咋办、单点登录

1. bean的生命周期

2.redis 数据库双写不一致

  1. 写请求串行化

写请求更新前先获得分布式锁,获得了才可以更新,否则就等待,等不到就更新失败。

更新完成后去刷新缓存,如果刷新失败,放到内存队列中进行重试。

读请求发现缓存中没有数据时,直接去读取数据库,读完更新缓存。

  1. 先更新数据库,异步删除缓存,删除失败就重试

(如果数据库是读写分离的,那么删除缓存时需要延迟删除,否则可能会在删除缓存时,从库还没有收到更新后的数据,其他读请求就去从库读到旧数据然后设置到缓存中。)

3.Spring作用

  1. IOC思想:方便解耦,简化开发,把对象的创建和依赖关系维护交给Spring容器管理;

  2. AOP:所谓“切面”,简单说就是将那些与业务无关,却被业务模块所共同调

    用的功能封装起来,以减少系统的重复代码,降低模块之间的耦合度,增加系统的可维护性。AOP 的作用在于分离系统中的核心关注点和横切关注点,可以实现在不改变原程序的基础上,为代码增加新的功能

  3. 声明式事务的支持:只需要通过配置就可以完成对事务的管理,无须手动编程

  4. 可以方便集成各种框架

  5. 事务管理(ACID)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值