java笔试面试总结

java基础

  1. 面向对象三要素:封装、继承、多态
    多态:同一操作作用于不同的对象,可以产生不同的效果
    方法的重写Overriding和重载Overloading是java多态性的不同表现。
    重写是父类与子类之间多态性的一种表现,重载是一个类的多态性的表现
  2. 抽象类中能包含普通方法或者定义变量,接口中不能定义普通方法。接口变量默认是public static final 型,其中不能含有静态代码块以及静态方法

对象的整个生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段(Finalized)与释放阶段(Free)

  1. Object类常用的方法有哪些?
    wait:final方法。作用:阻塞当前线程,且当前线程必须拥有此对象的monitor(即锁)
    notify:final方法。作用:唤醒一个正在等待该对象monitor的线程。如果有多个线程都在等待该对象的monitor,只唤醒一个
    notifyAll:final方法。作用:唤醒所有等待该对象monitor的线程
    toString:
    equals:
    hashcode:Object里hashCode()里面只是返回当前对象的地址。有时候不同的对象生成的hashcode也会一样(生成hash值得公式可能存在的问题)
    注意:equals相等则hashcode肯定相等,反过来不一定
  2. 基本类型 Integer的自动拆装箱(-128,127),Byte,Char,Short,Long

一个字节: byte,boolean; -128到127
两个字节: short,char;
四个字节:int,float,
八个字节:long,dobble

  1. Hash相关:
    a: hashMap基于hashing原理,通过key的hashCode()方法计算hashcode。发生碰撞采用链表(单向)。默认大小16,扩展因子0.75。1.8扩容是将之前的hash值与原容量oldCap作与运算(e.hash & oldCap) == 0则在原位置,否在在原位置+oldCap下在这里插入图片描述
    hashMap:非synchronized,非线程安全,允许key和value同时为null
    hashTable:synchronized,线程安全的,不允许key和value的值null
    TreeMap保存了对象的排列次序
    b: HashSet实现了Set接口,它不允许有重复的值.确保对象重写equals()和hashCode()方法HashSet仅仅存储对象
    c: ConcurrentHashMap可以多线程访问将Map分段了,每个段进行加锁,而不是像Hashtable,SynchronizedMap是整个map加锁。1.8之后Node + CAS + Synchronized+红黑树 来保证并发安全进行实现
    d: SynchronizedMap操作HashMap时自动添加了synchronized来实现线程同步。线程安全的map有: hashtable\synchronizedMap\concurrentHashMap
    e: LinkedHashMap: 基于HashMap,每个节点之间又是双向链表。输出时是按输入的顺序。
    HashMap初始化时,会是输入参数的最小的2的n次幂,
    计算key在map中的索引位置:[ (n - 1) & hash] hash是key的hash值
    1.8采用尾插入,之前是头插入。结点个数小于等于6则用链表,大于等于8用红黑树。因为6/2=3, 8/2=4,log(8)=3。红黑树的查找、插入、删除的时间复杂度最坏为O(log n)
  2. 集合
    Collection是集合类的上级接口;Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作
    在这里插入图片描述
    a: ArrayList和Vector都是使用数组方式存储,LinkedList是双向链表。
    ArrayList和LinkedList不是线程安全的,Vector使用了synchronized方法,是线程安全的。ArrayList扩容0.5;Vector扩容1倍。
    b: Collection是集合类的上级接口,继承他的有List和Set。Collections是集合类的帮助类,提供静态方法实现对集合的搜索、排序、线程安全化等操作。
    c: HashSet是基于HashMap的,元素都存到HashMap键值对的Key上面,而Value时有一个统一的static final的Object值。TreeSet会 对Set集合中的元素进行排序,和HashSet一样都非线程安全。set集合中采用equal()判断对象是否相同。
    d: Array和ArrayList的区别:array固定大小,arrayList可自动扩展;array可以存储基本类型和对象类型,arrayList只能存对象类型;arrayList有addAll(),removeAll(),iterator()等方法。
    e: Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在集合外部实现的排序
  3. 常见的异常
    编码错误(编译器提示)
    运行错误Exception
    Error是虚拟机内部错误
    在这里插入图片描述
    throw和throws的区别:throw是语句抛出一个异常;throws是方法可能抛出多个异常的声明,hrows E1,E2,E3
  4. NIO
    NIO 主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统 IO 基于字节流和字符流进行操作,而 NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

非阻塞: 使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。

  1. 泛型
    创建对象或调用方法的时候才去明确特殊的类型。
    泛型类中的静态方法和静态变量不能使用泛型类所声明的泛型类型参数。
    类型擦除:java的泛型是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉
    泛型变量不能是基本数据类型:类型擦除后,ArrayList的原始类型变为Object,但是Object类型不能存储基本数据类型(dubbo)的值,只能应用封装类型(Dubbo)的值

  2. 引用

  • 强引用:当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象
  • 软引用:如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
  • 弱引用:在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
  • 虚引用:如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

多线程

  1. 锁相关
    Synchronized和Lock(ReentrantLock)的区别:synchronized锁机制由JVM维护,在竞争不激烈的情况下性能更好(会根据锁的竞争情况,从偏向锁–>轻量级锁–>重量级锁升级)。在对象头和栈帧中的锁记录中存储偏向锁的线程ID。Lock功能更强大更灵活,竞争激烈时性能较好(需要手动释放,在finally块中unlock()资源);synchronize可以用在代码块上,方法上,会自动释放锁,无法相应中断,非公平锁。lock只能写在代码里,不能直接修改方法,能够响应中断.

  2. 如何预防死锁:
    a、尽量使用tryLock(long timeout, TimeUnit unit)方法(ReetrantLock, ReetrantReadWriteLock),设置超时时间,超时可以退出防止死锁。
    b、尽量使用java.util.concurrent并发类代替自己手写锁,
    c、尽量降低锁的使用粒度,尽量不要几个功能用同一把锁
    d、尽量减少同步的代码块

  3. 乐观锁
    乐观锁避免了悲观锁独占对象的现象,提高了并发性能
    缺点:乐观锁只能保证一个共享变量的原子操作,如果有多个变量,乐观锁无能为力,但互斥锁能解决,不管有多少对象一级对象的颗粒度大小;长时间自旋会给CPU带来很大的开销;ABA问题,赋值时不考虑过程,对依赖过程值的情景运算结果影响很大,解决思路是引入版本号。

  4. ThreadLocal
    ThreadLocal为每一个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
    ThreadLocal使用场景是数据库连接和session管理

  5. volidate关键字
    多线程情况下,当jvm开启优化性能时,强制线程在使用volidate修饰的变量时,从主内存中读取,不从线程副本内存中读取变量,从而保证变量的同步安全。还会禁止指令重排。Volatile 修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。

  6. CountDownLatch在多线程并发编程中充当一个计时器的功能,并且维护一个count的变量,并且其操作都是原子操作,该类主要通过countDown()和await()两个方法实现功能的

  7. CyclicBarrier 所有的线程必须同时到达栅栏位置,才能继续执行。栅栏用于等待其他线程。
    // 申明,等待线程数量 3次
    CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
    cyclicBarrier.await(); // 等待其他线程完成

  8. 线程池
    ExecutorService es1 = new ThreadPoolExecutor(cor,max,time,unit,
    workQueue,threadFactory,rejectHandler);
    es1.execute(new Runnable(){});

ExecutorService es2 =Executors.newFixedThreadPool(10);
Future feature2 = es2.submit(new Callable() { });

a、 Executors.newScheduledThreadPool():
b、 Executors.newFixedThreadPool(int n):一个可重用固定个数的线程池.核心和最大都是n,队列是无限的LinkedBlockingQueue,等待时间为0
c 、 Executors.newCacheThreadPool():可缓存线程池,先查看池中是否存在,有则直接食用,否则新建一个线程放入池中,该线程池通常用于执行一些生存期很短的异步型线程。
d、 Executors.singleThreadPool():创建一个单线程化的线程池
1、corePoolSize:核心线程数
2、 BlockingQueue: 阻塞队列:
直接提交的任务队列SynchronousQueue;
有界的任务队列ArrayBlockingQueue;
无界的任务队列LinkedBlockingQueue;
优先任务队列PriorityBlockingQueue。
3、maxPoolSize:最大线程数
4、keepAliveTime:线程空闲时间
5、TimeUnitunit:时间单位
6、 handler:表示当 workQueue 已满,且池中的线程数达到 maxPoolSize 时,线程池拒绝添加新任务时采取的策略。抛出异常(默认),抛弃最旧的任务,抛弃当前任务,由提交任务是线程执行
7、 threadFactory:指定创建线程的工厂
IO密集型=2Ncpu;
计算密集型=Ncpu
6. synchronized原理
synchronized是由一对monitorenter/monitorexit指令实现的,偏向锁、轻量级锁、重量级锁。对象头,monitor对象。悲观锁
Synchronized用在类定义上是类锁(该类的所有对象用同一把锁),用在方法上是对象锁(修饰静态方法是类锁)。synchronized (A.class) 类锁,synchronized (this) 对象锁。synchronized

  1. 如何保证多线程的运行安全?
    使用安全类,比如java.util.concurrent下的类
    使用自动锁synchronized
    使用手动锁Lock
  2. final、finally、finalize的区别
    final: 用于声明属性、方法和类,分别表示属性不可变,方法不能覆盖,类不能继承。内部类访问局部变量,局部变量必须定义成final类型。
    finally: 是异常处理语句结构的一部分,表示总是执行(catch中是否执行要看try中是否存在异常)
    finalize: Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,
  3. CAS算法
    CAS(Compare and Swap, 比较并交换),涉及到内存值、预期值、新值。当且仅当内存值和预期值相等时才将内存值修改为新值。CAS是乐观锁的核心算法。
    java.util.concurrent.atomic下的类是基于CPU的CAS指令来实现线程安全
    悲观锁适用于写频繁的场景
    乐观锁适用于读频繁的场景
  4. AQS
    AbstractQueuedSynchronizerr抽象的队列式同步器。如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁定状态,如果资源被占用,那么就需要一套(线程阻塞等待以及被唤醒时锁分配)的机制,通过CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,虚拟的双向队列即不存在队列实例,仅存在节点之间的关联关系。

AQS是将每一条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node),来实现锁的分配。AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。注意: AQS是自旋锁,在等待唤醒的时候,经常会使用自旋(while(!cas()))的方式,不停地尝试获取锁,直到被其他线程获取成功

  1. 线程状态转换
    新建状态、就绪状态、运行状态,阻塞状态,死亡状态。
    对象等待池(wait())、对象锁池、其他阻塞状态(sleep(),join())

  2. ForkJoin: 将一个复杂的计算,按照设定的阈值进行分解成多个计算,然后将各个计算结果进行汇总

虚拟机

-Xmx1024m: 设置应用程序(不是JVM)能够使用的最大内存数
-Xms256m: 设置程序初始化时内存栈的大小
-Xmn2g:设置年轻代大小为2G
-Xss128k:设置每个线程的堆栈大小
-XX:NewRatio=4: 年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

  1. 类加载过程:加载,连接,初始化。
    加载: Java虚拟机查找字节流(查找.class文件),并且根据字节流创建java.lang.Class对象的过程。将类的.class文件中的二进制数据读入内存,放在运行时区域的方法区内。然后在堆中创建java.lang.Class对象,用来封装类在方法区的数据结构。
    链接: 包括验证、准备以及解析三个阶段。
    验证:确保被加载的类(.class文件的字节流)满足Java虚拟机规范,不会造成安全错误。
    准备:负责为类的静态成员分配内存,并设置默认初始值。
    解析:将类的二进制数据中的符号引用替换为直接引用。
    初始化: 为标记为常量值的字段赋值的过程。换句话说,只对static修饰的变量或语句块进行初始化。
    如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
    如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
  2. 内存区域分配:堆,栈,方法区,常量池,程序计数器
    堆: 通过new创建的对象都放在堆中,对堆中对象生命周期的管理交于java虚拟机的垃圾回收机制GC进行统一回收和管理。优点是可以动态分配内存大小,缺点是由于动态分配内存导致存取速度较慢。堆被所有线程共享,在虚拟机启动时创建,是gc的主要区域。
    栈: 函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配。栈中的数据可以共享,但存在栈中的数据大小和生存期必须是确定的,缺乏灵活性。

栈帧:栈帧是虚拟机栈的栈元素,用于虚拟机方法调用和方法执行的数据区域,包括方法的局部变量表、操作数栈、动态链接和方法返回地址。
局部遍历表:是变量值的存储空间,最小单位是slot(变量槽)。一个slot存放一个boolean、byte、char、short、int、float、reference、returnAddress类型
方法返回地址:方法调用者的PC计数器的值,用以回复调用者的执行状态

方法区: 各个线程共享的内存区域,用于存储class二进制文件,包含虚拟机加载的类信息,常量,静态变量,即时编译后的代码等数据。
常量池: 在编译期间就将一部分数据存放于常量池,包含以final修饰的基本数据类型的常量值,String字符串。
程序计数器: 当前线程所执行的行号指示器。通过改变计数器的值来确定下一条指令,比如循环,分支,跳转,异常处理,线程恢复等都是依赖计数器来完成。

新生代=1/3,对应Minor GC,复制算法; 老年代=2/3 对应Major/full GC,标记整理算法
新生代=Eden(8) + from Survivor(1) + to Survivor(1)
大对象直接进入老年代,在Eden的对象经过一次Minor GC后仍然存活,并且能为Survivor容纳的话,将被移动到Survivor空间中,年龄=1,一次Minor GC都会年龄加一,默认到15,晋升到老年代。

类加载器: 从顶层到底层,分为三种:
启动类加载器(Bootstrap ClassLoader):存放在JAVA_HOME/lib下的,并且是虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。
扩展类加载器(Extension ClassLoader);
应用程序类加载器(Application ClassLoader):负责加载用户类路径(Classpath)上所指定的类库,程序中默认的类加载器

双亲委派模型: 一个类收到类加载请求,它首先把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,因此所有的加载请求最终都应该传递到顶层的启动类加载器中,只有父类加载器反馈自己无法完成时,子加载器才会尝试自己去加载。

不采用双亲虚拟机只有在两个类的类名相同且加载该类的加载器均相同的情况下才判定这是一个类。若不采用双亲委派机制,同一个类有可能被多个类加载器加载,这样该类会被识别为两个不同的类,相互赋值时会有问题。

jmap:观察运行中的jvm物理内存的占用情况。
jps:与unix上的ps类似,用来显示本地的java进程
jinfo:输出并修改运行时的java进程的运行参数

垃圾回收GC

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

  1. 如何判断对象需要被回收(GC):引用计数算法,可达性分析算法

  2. 垃圾回收算法:(垃圾回收器不可以马上回收内存)
    标记-清除算法: 首先标记需要回收的对象,在标记完成后统一回收
    复制算法: 将内存按容量划分为大小相同的两块,每次只使用一块,当这一块内存用完了,将存活的对象复制到另外一块上面。适用于新生代
    标记-整理算法: 将存活的对象移动到一端,然后清理掉其他。适用于老年代
    按代回收 新生代用复制,老年代用标记整理

  3. 垃圾回收机制什么时候触发?
    GC有两种类型:Full GC & Scavenge GC 。
    FullGC: 在优先级最低的线程中运行,一般在应用程序空闲(没有应用线程在运行)时被调用。对整个堆进行整理,包括新生代,老年代和静态区。因为Full GC要对整个堆回收,所以比较慢,应尽量减少Full GC 的次数
    Scavenge GC Java堆内存不足时,Scavenge GC会被调用。若GC一次之后仍不能满足内存分配,JVM会再进行两次GC,若仍无法满足要求,则JVM将报“out of memory”的错误,java虚拟机将停止运行。

  4. 垃圾收集器
    Serial收集器: 单线程收集器,进行垃圾回收时,必须暂停其他所有的工作线程(Stop the world).采用复制算法,目前仅用在Client模式下
    ParNew收集器: ParNew收集器是Serial收集器的多线程版本。Server模式下的新生代收集器,除了Serial收集器外,只有他能和CMS收集器配合工作。默认开启线程数和CPU数量相同,在单CPU的环境中没有Serial收集器效果好。
    Parallel Scavenge收集器: 新生代收集器,采用复制算法,并行的多线程收集器。达到可控制的吞吐量。
    Serial Old收集器: 是Serial 收集器的老年代版本,是单一线程的收集器,采用“标记-整理“算法。给Client模式下的虚拟机使用,作为CMS收集器的预备方案。
    Parallel Old收集器: 是Parallel Scavenge的老年代版本,采用“标记-整理”算法。在注重吞吐量以及CPU资源敏感的场合,可以考虑Parallel Scavenge加Parallel Old收集器。
    CMS收集器: 以获取最短回收时间为目标的收集器,采用标记清除算法。运作方式:初始标记,并发标记,重新标记,并发清除。优点:并发清除,低停顿。缺点:并发清除阶段用户线程还在运行,这样就会有新的垃圾不断产生
    G1收集器: Garbage-First,面向服务端应用的垃圾收集器。分代回收,整体上看采用“标记-整理“算法,局部(两个Region间)看是“复制算法”。除了追求低停顿外,还能简历可预测的定低顿时间模型。

析构函数的作用:用于在撤销对象前,完成一些清理工作,比如:释放内存等。
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。

内存泄露: 长生命周期的对象持有短生命周期对象的引用;当一个对象被存储进HashSet集合中以后,修改这个对象中的那些参与计算哈希值的字段

数据库

事务的属性: 原子性Atomic,一致性Consistent,隔离性Isolated,持久性Durable

  1. 数据的隔离级别:
  • 共享锁:S锁,是一种读锁,当一个事务获得了一条数据的共享锁,其它事务也能获得该共享锁,但不能获得排他锁,表明其它事务可读。共享锁保证大家可以一起读,但只能一个人写。
  • 排他锁:X锁,是一种写锁,当一个事务对临界区加上排他锁,其它事务就不能获得该临界区的任何锁(共享锁,排他锁)。排他锁保证只能一个人去处理数据,其他人不能读也不能写。
    1、未提交读Read uncommitted
    原理:写时加上排他锁,直到事务结束, 读的时候不加锁。
    2、已提交读Read committed :解决脏读(事务A的读取到的数据被事务B回滚了)
    原理:写时加上排他锁, 直到事务结束,读时加上共享锁,读完立刻释放。
    3、可重复读Repeatable read :解决幻读(事务A第一次读取的行数和第二次读取到的行数不同,被事务B修改过)
    原理:写时加上排他锁,直到事务结束, 读时加共享锁, 事务提交之后立刻释放。
    4、可序列化Serializable:解决不可重复读(事务A读取两次的值不一样,该值被事务B修改过)
    原理:事务写数据则加表级排他锁,事务读数据则加表级共享锁。

隔离级别如何实现? 使用MVCC(多版本并发控制)+锁机制。 每行数据其实在数据库都是多个版本的,可能同一时间有很多事务在更新一条数据,事务在开始的时候会申请一个id,这个id是严格随着时间递增的,先开始的事务id总是小的,数据库的版本就是事务id的版本。
可序列化:用加锁的方式来避免并行访问。

  • 索引类型: 主键索引,唯一索引,普通索引
  • InnoDB通过主键的聚集索引(叶子结点包含完整的数据记录)保存记录。InnoDB的辅助索引data域存储相应记录主键的值而不是地址。MyIsam中叶子结点包含值和对应的数据在磁盘上的地址。(如果是String类型的,通过ASCII码对比)
  1. 三范式:
    第一范式:强调列的原子性,即数据库表的每一列都是不可分割的原子数据项。
    第二范式:保证一张表只描述一件事情
    第三范式:保证每列都和主键直接相关
    innodb会把自增主键最大Id记录在内存中,所以重启后会导致最大id丢失。
  2. explain相关
    id: 执行顺序,id相同时,执行顺序从上到下,id越大优先级越高
    select_type: 简单查询还是复杂查询
    simple:简单查询。查询不包含子查询和union
    primary:复杂查询中最外层的 select
    subquery:包含在 select 中的子查询(不在 from 子句中)
    derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)
    table:
    type: 查找行的方式,取值有:ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)
    all:遍历全表取到匹配行
    index:遍历索引树
    range:只检索给定范围的行
    ref: 虽然使用了索引,但该索引列的值并不唯一,有重复。
    ref_eq:使用了主键或者唯一性索引进行查找
    const/system:对查询的某部分进行优化并将其转化成一个常量。用于 primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。
    NULL:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表
    possible_keys: 查询字段上若存在索引,则该索引将被列出,但不一定被查询使用(如果没有任何索引显示 null)
    key: 实际使用的索引
    key_len: 索引里使用的字节数
    ref: 在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),func,NULL,字段名
    rows: 估算出结果集行数
    extra: 额外的一些重要字段
    distinct: 一旦mysql找到了与行相联合匹配的行,就不再搜索了
    Using index:查询的列都是同一索引的部分,查询条件是索引的前导列,返回的列数据只使用了索引中的信息,而没有再去访问表中的行记录。是性能高的表现。
    Using temporary:mysql需要创建一张临时表来处理查询。
    Using where:查询字段未被索引列覆盖,where条件也不是索引的前导列。就是先读取整行数据,再按 where 条件进行检查,符合就留下,不符合就丢弃。
    Using where Using Index: 查询字段在联合索引内,where条件是索引之一但不是前导列
    NULL:查询字段未被索引覆盖,且where条件是索引的前导列
    Using Index Condition:列不在索引中,where条件是前导列的范围
    Using filesort:mysql 会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时mysql会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息
  3. order by和group by会影响索引,和where一起,采用最左匹配原则。如果没有where语句,单纯的group by | order by 也是不会使用任何索引。
  4. 为何不用 select * 查询?
    用 * 需要去查询字典;其中包含不必要的字段增大IO,导致内存和cpu的消耗;如果包含大字段,可能会导致增加IO;在多线程修改表结构的情况下可能会导致查询失败。
  5. Innodb和myIsam
    Innodb支持外键、行锁、事务;myIsam只支持表锁;myisam允许没有任何索引和主键的表存在,Innodb如果没有会自动生成一个6字节的主键(用户不可见);myIsam中存有count的值。
  6. B树和B+树: 平衡多路查找树
    B+树是对B树的改进,内结点只作索引,使得每个结点中能够存放更多的key, 因此能有更大的出度.这样就能存放更多的key, 树的层高能进一步被压缩, 使得检索的时间更短。B+树的相邻叶子节点形成链。
  7. 存储
    InnoDB存储引擎的最小存储单元为16k(就像操作系统的最小单元为4k 即1页),在这即B+树的一个节点的大小为16k 。假设数据库一条数据的大小为1k,则一个节点可以存储16条数据。非叶子节点,key一般为主键假设8字节,指针在InnoDB中是6字节,一共为14字节,一个节点可以存储 16384/14 = 1170个索引指针。高度为3的树,可以存放 1170 * 1170 * 16 = 21902400条记录,两千多万条数据,我们只需要B+树为3层的数据结构就可以完成,通过主键查询只需要3次IO操作就能查到对应记录。
  8. 聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。一张表只能有一个聚簇索引。
  9. 非聚集索引与聚集索引的区别:非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据需要根据主键再去聚集索引中查找,这个再根据聚集索引查找数据的过程,称为回表。
  10. union 和 union All的区别:两个结果的行并集操作,不包括重复行;union All是两个合集的总和,包括重复行
  11. mybatis的逻辑分页和物理分页
    逻辑分页:将数据一次性从数据库查出到内存中,在内存中进行逻辑上的分页
    物理分页:直接特定的SQL语句,只从数据库中查询出需要的数据(适用于数据量较大的情况)
  12. 事务ACID特性的实现思想
  • 原子性:是使用 undo log来实现的,如果事务执行过程中出错或者用户执行了rollback,系统通过undo log日志返回事务开始的状态。
  • 持久性:使用 redo log来实现,只要redo log日志持久化了,当系统崩溃,即可通过redo log把数据恢复。
  • 隔离性:通过锁以及MVCC,使事务相互隔离开。
  • 一致性:通过回滚、恢复,以及并发情况下的隔离性,从而实现一致性
  1. #和$的区别:#更安全,对传入的参数加上引号,有预编译的功能。
  2. 各个课程排名前三的学生
    select * from score ta where
    (select count(*) fromscore tb where ta.sourceid= tb.sourceid and tb.score>ta.score) < 3 – 即成绩前3
    order by sourceid,score desc;
  3. 学生表中每位学生全部科目中的最高分
    select t1.* from 学生bai表 t1,
    (select 学号du,max(成绩zhi)as 成绩 from 学生表 group by 学号) t2
    where t1.学号=t2.学号 and t1.成绩=t2.成绩

Spring

  1. IOC: Inversion of Control ,是一种设计思想,意味着将设计好的对象交给容器控制,而不是传统的在自己的对象内部控制。传统方式是在对象内部主动创建(new)依赖对象,而IOC有专门的容器来创建这些对象,即IOC容器控制对象的创建、控制外部资源的获取。传统方式是在对象中主动获取依赖对象,而反转则是由容器帮我们创建及注入依赖对象,依赖对象的获取被反转了。

  2. 什么是依赖注入DI(Dependency Injection)?
    通过简单的配置,而无需代码就能获取自身所需要的资源,完成业务逻辑,而不需要关系具体的资源从哪里来,由谁创建。应用程序依赖于IOC容器,IOC容器提供对象所需要的外部资源,IOC容器注入应用程序所依赖的对象。
    控制反正和依赖注入是同一个概念的不同角度描述。

  3. 静态代理和动态代理
    静态代理:在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就已经确定了。
    动态代理:动态代理的源码是在程序运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件,代理类和委托类的关系是程序运行时确定的。只能基于接口进行代理。

  4. AOP
    Aspect Orient Programming,面向切面编程,两种实现方式:
    基于接口的动态代理(Dynamic Proxy):只能为接口创建动态代理实例,而不能对类创建动态代理;
    基于子类化的CGLIB代理:把被代理对象类的class文件加载进来,修改其字节码生成子类。实际上是生成了目标类的子类来增强,对final无计可施
    实现:引入相关jar包
    @Aspect
    @Component
    public class MyAspect {
    // 前置通知:目标方法执行之前执行以下方法体,还有@After
    @Before(“execution(* com.qcc.beans.aop..(…))”)
    public void beforeMethod(JoinPoint jp){ }

  5. Spring中bean的作用域:
    singleton:仅存在一个bean实例,bean以单例的方式存在
    prototype:每次请求都生产一个新的bean实例
    request:在bean请求范围内,为每一个网络请求创建一个实例,在请求完成后,bean会失效
    session: 每一个session会话创建一个bean, session过期后bean会失效
    globalSession:表示在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
    spring循环依赖问题解决?使用Singleton或者prototype

  6. Spring中的自动装配方式有哪些?
    no: 不自动装配,手动设置bean的依赖关系
    byName: 根据bean的名字自动装配
    byType: 根据bean的类型自动装配
    constructor: 类似于byType,不过是根据构造器中的参数类型;如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
    autodetect: 如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
    Spring注入的方式:构造方法注入、set注入、基于注解的注入

  7. servlet的生命周期:init(),service(),destroy()
    forward:地址不变,转发和转发到的页面共享request中的数据,效率高
    redirect:服务器让客户端重新发送请求,效率低
    getAttribute()返回对象;getParameter() 返回字符串

  8. spring的主要模块:
    Spring AOP 面向切面编程
    Spring ORM Hibernate|mybatis|JDO
    Spring Core 提供bean工厂 IOC
    Spring Dao JDBC支持
    Spring Context 提供了关于UI支持,邮件支持等
    Spring Web 提供了web的一些工具类的支持
    Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export

@Qualifier(“abc”)等同于@Resource(name=“abc”)
ClassPathResource在环境变量中读取配置文件,spring会在ClassPath中自动搜寻配置文件;FileSystemResource在配置文件中读取配置文件,需要给出spring-config.xml文件在你项目中的相对路径或者绝对路径

  1. BeanFactory和ApplicationContext的区别
    BeanFactory提供最简单的容器的功能,只有实例化对象和拿对象的功能;ApplicationContext继承BeanFactory接口,它是Spring更高级的容器,提供了更多的有用的功能: 国际化、 访问资源、 载入多个(有继承关系)上下文、消息发送、响应机制、 AOP(拦截器)
    BeanFactory在启动时不实例化bean,从容器中拿bean的时候才实例化;ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化;
  2. Spring主要包括了三种配置bean元数据的方式:XML文件;java注解; java代码:在配置类上加入 @ComponentScan(“com.study”)//相当于xml中配置到 扫描包。
  3. bean的生命周期:
    1、实例化bean对象(通过构造方法或者工厂方法)
    2、设置对象属性(setter等)(依赖注入)
    3、如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
    4、如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
    5、将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
    6、调用Bean的初始化方法
    7、将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法使用Bean
    8、容器关闭之前,调用Bean的销毁方法
  4. 常用的注解
    @ComponentScan ;@Configuration;@RestController(标注控制层组件);@RequestMapping(访问地址);@Service用于标注业务层组件;@Repository;@Mapper;@Component(泛指组件,当组件不好归类时,使用这个注解进行标注);@Autowired(按类型);@Resource(按名称)
  5. @Scheduled定时任务三种定时类型
  • cron表达式:@Scheduled(cron=“0/5 * * * *?”)
  • fixedRate: @Scheduled(fixedRate=2000) 每两秒执行一次,程序启动时开始。
  • fixedDelay: @Scheduled(fixedDelay=2000) 任务执行完成后推迟2秒继续执行。
    如果任务冲突,采用@Bean TaskScheduler,创建ThreadPoolTaskScheduler设置线程池
  1. spring mvc的请求过程
    在这里插入图片描述
  2. Spring中使用的设计模式:
    单例模式,适配器,代理模式,简单工厂,工厂, 观察者,策略,包装器

网络

  1. UDP(User Datagram Protocol)用户数据报协议:利用Ip提供的面向无链接的服务,将应用程序发来的数据包立刻原样发送出去的一种机制。在网络拥堵的情况下,无法进行流量控制;如果传输过程中出现丢包,也不负责重发;数据包到达顺序出错,也不能纠正顺序;UDP面向无连接,适用于数据报总量较少的通信、音频视频对实时性要求高的多媒体传输;广播通信、多播通信
  2. TCP如何保证可靠传输?
    确认+重传:接收方收到数据包就确认,发送方经一段时间没收到报文就重传;
    检验和: TCP 将保持它首部和数据的检验和。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
    拥塞控制: 当网络拥塞时,减少数据的发送。
    流量控制:当接收方来不及处理发送方的数据时,内够降低发送速率,防止丢包。
  3. 网络协议
    应用层
    表示层
    会话层 应用层 应用程序能够直接运行于传输层之上,直接为用户提供服务。FTP、SMTP、WWW、HTTP等
    传输层 传输层 对应用层传递过来的用户信息分成若干数据报,加上报头,便于端到端的通信。TCP、UDP
    网络层 网络层 提供跨多个网络的寻址选路功能,使IP数据(带有IP地址)从一个网络的主机传到另一网络的主机。
    数据链路层 数据链路层 信息以帧(frame)为单位传输。所谓的帧,是一段有限的0/1序列,包括帧头、数据部分、帧尾
    物理层 物理层 指光纤、电缆或者电磁波等真实存在的物理媒介
  4. 三次握手过程分析:
    第一次:客户端发送请求到服务器,服务器知道客户端发送,自己接收正常。SYN=1,seq=x
    第二次:服务器发给客户端,客户端知道自己发送、接收正常,服务器接收、发送正常。ACK=1,ack=x+1,SYN=1,seq=y
    第三次:客户端发给服务器:服务器知道客户端发送,接收正常,自己接收,发送也正常.seq=x+1,ACK=1,ack=y+1
  5. 四次挥手
    (1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
    (2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(FIN+1),Server进入CLOSE_WAIT状态。
    (3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
    (4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1(ack+1),Server进入CLOSED状态,服务器端收到ACK后,就知道可以断开连接了。客户端等待了2MSL(最长报文段寿命)后依然没有收到回复,则证明服务器端已正常关闭,则客户端也可以关闭连接了。

1XX:通知;2XX: 成功;3XX 重定向;4XX:客户端错误;5XX 服务端错误
202表示请求已经被接受,但是还没有处理完
503:由于临时的服务器维护或者过载,服务器当前无法处理请求
502(错误网关):服务器作为网关或代理,从上游服务器收到了无效的响应。
504(网关超时):服务器作为网关或代理,未及时从上游服务器接收请求。

http请求过程:
1.对www.baidu.com这个网址进行DNS域名解析,得到对应的IP地址
2.根据这个IP,找到对应的服务器,发起TCP的三次握
3.建立TCP连接后发起HTTP请求
4.服务器响应HTTP请求,浏览器得到html代码
5.浏览器解析html代码,并请求html代码中的资源(如js、css图片等)(先得到html代码,才能去找这些资源)
6.浏览器对页面进行渲染呈现给用户
https请求过程:
在这里插入图片描述

dubbo

  1. Dubbo提供了哪3个关键功能?

    • 基于接口的远程调用
    • 容错和负载均衡
    • 自动服务注册和发现
  2. 各个业务层、服务层之间的调用通过RPC技术,存在以下问题:
    1、 地址维护(服务越来越多,URL配置管理变得非常困难)
    2、 负载均衡
    3、 限流/容错/降级
    5、 链路监控

  3. 负载均衡策略
    在这里插入图片描述

  4. 核心配置:dubbo:service/ dubbo:reference/ dubbo:protocol/ dubbo:registry/ dubbo:application/ dubbo:provider/ dubbo:consumer/ dubbo:method/

  5. 其他分布式框架:spring cloud ;facebook的thrift;twitter的finagle等

  6. dubbo采用Zookeeper的watch机制实现数据变更,默认使用NIO Netty通信框架

  7. dubbo支持什么协议?
    dubbo://(推荐)rmi:// hessian:// http:// webservice:// thrift:// memcached:// redis:// rest://

  8. Dubbo内置了哪几种服务容器?
    Spring Container ;Jetty Container;Log4j Container

  9. 在 Provider 上可以配置的 Consumer 端的属性有哪些?
    1)timeout:方法调用超时
    2)retries:失败重试次数,默认重试 2 次
    3)loadbalance:负载均衡算法,默认随机
    4)actives 消费者端,最大并发调用限制

  10. Dubbo推荐使用什么序列化框架,你知道的还有哪些?
    推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。

  11. Dubbo和SpringCloud的区别
    a. Dubbo是RPC框架;SpringCloud是微服务框架
    b. Dubbo基于RPC;SpringCloud基于HTTP的Rest风格
    c. DUbbo的注册中心可以使用Zookeeper或者Redis;SpringCloud只有eureka

  12. Dubbo与http的比较
    dubbo是长链接,不必每次通信都要像http 一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统 一化的操作;编写代码时不用维护复杂的http地址,像直接调用本地接口。

其他

redis支持的数据类型:String,hash,list,set,Zset
1、redis的持久化方式:RDB 和 AOF

  • RDB(Redis DataBase)持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
    缺点:系统一旦在定时持久化之前出现宕机,此前没有来得及写入磁盘的数据都将丢失;RDB通过fork子进程来完成数据持久化,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
  • AOF(Append only file)持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。同步策略:每秒同步、每修改同步和不同步。
    缺点:AOF文件通常要大于RDB文件,恢复数据效率低。
    2、CAP
    一致性(Consistency):在分布式系统完成某写操作后任何读操作,都应该获取到该写操作写入的那个最新的值。
    可用性(Availability):客户端一直可以正常访问并得到系统的正常响应
    分区容错性(Partition tolerance):分布式系统中的某个节点或者网络分区出现了故障,整个系统仍然能对外提供满足一致性和可用性的服务
    zookeeper保证了一致性和可用性,即CA.
    maven查用的标签 groupId、version、dependency、exclusion
    mvn clean compile;mvn clean package
    在这里插入图片描述
    对称加密: :A与 B 之间的通讯数据都用同一套的密钥来进行加解密。
    非对称加密: A 的公钥加密过的东西只能通过 A 的私钥来解密;同理,A 的私钥加密过的东西只能通过 A 的公钥来解密。公钥是公开的,别人可以获取的到;私钥是私有的,只能自己拥有。

Tomcat 在处理少数非常繁忙的连接上更有优势,也就是说连接的生命周期如果短的话,Tomcat 的总体性能更高。Jetty 可以同时处理大量连接,而且可以长时间保持这些连接。例如像一些 web 聊天应用非常适合用 Jetty 做服务器,像淘宝的 web 旺旺就是用 Jetty 作为 Servlet 引擎。
详情:https://www.cnblogs.com/small-boy/p/8042860.html

Linux

  1. top命令,找到cpu占用最高的进程
  2. 查看该进程的线程, top -p
  3. ctrl+H 切换到线程模式,找到占用cpu最高的线程。并把线程号转化为十六进制,printf “%x\n” <线程ID>
  4. jstack <进程号>,把线程栈打印出来。找到对应的线程号就可以分析为什么线程会占用那么高的cpu了。
  5. ls -lsh:查看文件夹按大小排序输出
    -l表示以长格式显示,即列出文件详细信息如上面的格式。
    -s表示排序,默认是降序排列。
    -h表示将文件大小转为我们习惯的M,K等为单位的大小
  6. 以ab字母(忽略大小写)开头: cat file | grep -i ^ab
    awk -va=1 ‘{print $1,$1+a}’ log.txt:定义一个变量a=1,
    将log文件中的第一列和第一列+1的值打印出来,如果第一列没有数字,显示默认值1
  7. sed命令:操作文件内容。
    sed -e ‘4 a newline\nnewline2’ testfile:在testfile文件的第四行添加两行。
  8. ps命令瞬间进程的状态;如果想对进程进行实时监控应该用top命令。
  • 查找当前服务的进程:ps -ef|grep 服务名
  • 查找所有的Java进程:ps -ef|grep java
  • 查看哪些进程打开了指定端口1487 :lsof -i:1487
  1. vim下要查找字符串的时候, 都是输入 / 或者 ?输入 /super 或者 ?super。/是从上往下搜索,?是从下往上搜索。

PID 进程的ID号!
PPID 父进程的ID;
C CPU使用的资源百分比
PRI指进程的执行优先权(Priority的简写),其值越小越早被执行;
SZ 使用掉的内存大小;
TIME 使用掉的 CPU 时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值