当前位置:   article > 正文

Java面试高频考点#简答题型整理#基础、并发、框架、中间件、存储(非常实用)_java中间件选择题

java中间件选择题

  Java面试高频简答题型整理汇总,总共是5大部分,基础题型(34道)、并发题型(18道)、框架题型(15道)、中间件题型(7道)、存储题型(21道),此篇总结并没有深入原理,主要用于基础概念的回顾,形成一个较全面的知识体系,适合初级、中级Java开发程序猿!
  如有错误,请指正!

1.基础题型
1.1.简述java中的BIN、NIO、AIO的区别

   BIN:阻塞IO,一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理;

   NIO:非阻塞IO,服务器实现模式为一个请求一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用轮询到连接I/O请求时才启用一个线程进行处理;

   AIO:异步非阻塞,客户端的I/O请求都是由系统完成了再通知服务器应用再去启用线程进行处理(系统调用用回调处理)

1.2.接口可以多继承吗?

   Java中类是单继承,可以实现多个接口,但是接口与接口之间可以多继承,例如:

   Interface B extends A,C {

   }

   这种语法是没有问题的。

1.3.创建一个线程有几种方法?

第一种:继承Thread类

public class T1 extends Thread{
	
}
  • 1
  • 2
  • 3

第二种:实现Runnable接口

Public class T2 implements Runnabled{

   //实现run接口

   Public void run{
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第三种:实现Callable接口

//callable 接口支持泛型,代表返回值的类型
Public class T3 implements callable<long>{
	//需要实现call函数,并且有一个返回值
	//可以抛出异常
	Public Long call() throws Exception{
	return 1;
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

   在使用时需要使用FutureTask类包装一下FutureTask task=new FutureTask(t3);

   包装类完成后才能是用Thread类中start方法启动 new Thread(task).start();

   启用后可以使用task.get()获取返回值,如果线程没有执行完,该方法会一直阻塞到线程执行完毕。

   另外可以使用task.isDone()函数校验线程是否执行完毕,该方法不会被阻塞。

   Java自带线程池可以使用submit(t3)来提交任务到线程池,并且接收一个Future类型的返回值,通过Future.get()函数获取返回值。Future.isDate()校验是否执行完毕。

1.4.列举出项目中常用设计模式,并给出一个实际例子:

总共有23种设计模式,以下为一些常见的设计模式,也容易被问到的设计模式:

   (1)单例模式:Spring中的Bean默认都是单例的,另外系统中的Runtime、Calendaer都是单例的,注意单例模式的七种写法,其实servlet也是单例,但是一个伪单例;

   (2)抽象工程(简单工程):Spring中的BeanFactory就是一个抽象工厂;

   (3)享元模式:又称为池化技术,例如:数据库连接池,线程池等;

   (4)装饰器模式:JDK中的IO相关类就是使用的装饰器模式;

   (5)门面模式:slf4j.Logger就是使用的门面模式;

   (6)代理模式:Spring AOP就是使用代理模式,另外注意经jdk的动态代理,和cglib的动态代理区别;

   (7)观察者模式:Spring 中ApplicationListener 事件的通知,比如MQ,都是观察者模式的运用。

1.5.什么是双亲委派机制?

   当类加载器收到类加到需求时,会优先委托给父类加载器加载,如果父类加载器可以加载,则直接返回父类加载的结果,如果父类无法加载在去尝试自己加载;

   这样可以提高安全性,也避免系统类被串改导致的安全问题;

   自定义类加载器,可以打破双亲委派机制。

1.6.说说JVM中的类加载机制?

   (1)加载阶段:加载.Class二进制内容到内存(来源不一定是.class文件也有可能是来源网络,或是数据库等。);

   (2)验证阶段:验证文件内容的格式是否完整,是否符合当前虚拟机规范,版本是否合适等;

   (3)准备阶段:给非final修饰的静态(static)变量分配内存空间,并且赋初始值;

   (4)解析阶段:把符号引用转换为直接引用;

   (5)初始化阶段:执行初始化步骤,并且给final修饰的静态变量赋值。

1.7.java.sql.Date和java.util.Date有什么不一样Sql.Date有什么用

   Java.sql.Date继承了java.util.Date;

   Java.sql.Date是JDBC的日期处理格式,只保存了年月日,时分秒毫秒都会清零;

   另外java.sql.Date没有序列化功能的环境中不可能使用,例如:分布式系统的RPC调用。

1.8.设计模式的六大原则是什么?

   (1)单一职责原则:单一职责原则指的是有且仅有一个原因引起类的变更;

   (2)里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象;

   (3)依赖倒置原则:抽象不应该依赖于细节,细节应该依赖于抽象。换言之:要针对抽象(接口)编程,而不是针对实现细节编程;

   (4)接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一类的依赖应用建立在最小的接口上;

   (5)米特法则:也称为最少知识原则,一个对象应该对其他的对象有最少的了解,一个类只需要知道自己许哟啊耦合或者调用类的public方法即可;

   (6)开闭原则:对扩展开发对修改关闭

​   总计:任何原则都是为了代码的解耦复用。

1.9.什么时候进行GC?

   Minor GC在年轻代的Eden区满了或不足以存放新对象的时候会进行,另外在Full GC之前也会先执行Minor GC;

   Full GC 老年代满了或方法区满了或放不下新搬入老年代的对象的时候会进行Full GC另外调用System.gc()时候也可能会执行Full GC。

1.10.线程池的5个参数都是什么?有什么含义?

   (1)corePoolSize:核心线程数量,默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数中的线程数目到corePoolsize后,就会把到达的任务放到缓存队列当中。核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出;

   (2)MaxPoolSize :最大线程数量,当线程数大于或等于核心线程数(corePoolSize),且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolsize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常;

   (3)KeepAliveTime:空闲时间,当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize;如果allowCoreThreadTimeOut设置为true,则所有线程均会退出直到线程数量为0;

   (4)AllowCoreTheadTimeout:是否允许核心线程空闲退出,默认值为false;

   (5)QueueCapacity:队列容量(大小),最大能容纳等待的任务数量;

注意:线程池拒绝任务的策略有四种:

   ①丢弃任务并输出RejectedExecutionException异常

   ②丢弃任务,但是不抛出异常;

   ③队列最前面的任务,然后重新尝试执行任务(重复此过程)

   ④调用线程处理任务。

1.11.JVM常用参数有哪些?有什么意思?

   - Xms256M 初始化堆大小(通常和最小堆大小一致,避免虚拟机平方自动计算机调整堆大小)

   -Xmx256M 最大堆大小;

   -Xmn256M新生代大小(官方推荐配置为整个堆的3/8)

   -Xss128k 每个线程的大小

   -XX:NewRatio=4 年轻代与老年代的大小比值

   -XX:NewSize=年轻代大小

   -XX:MaxNewSize=年轻代最大值

   -XX:SurvivorRatio=8 Eden和survivor的比值

   -XX:PermSize=持久代的大小(1.8以后失效);

   -XX:MaxPermSize=设置持久代最大大小(1.8以后失效)

   -XX:MaxspaceSize=元空间内存大小(1.8以后失效)

   -XX:MaxMetaspaceSize=元空间最大大小(1.8以后失效)

   -XX:MaxTenuringThreshold=0 对象的最大年年龄(如果设置为0,则不经过Survivor区直接进入老年代)

   -XX:+PrintGCDetails打印GC日志

   -XLoggs:/ttemp/logs/gc.logs 指定GC日志输出文件名称、

   -XX:+HeadDumpOnOutMemoryError OOM时导出堆到文件

   -XX:HeadDumpPath=d:/a.dump 导出OOM的路径

   -XX:UserG1GC 使用G1垃圾收集器

1.12.线上引用频繁发生FULL GC需要怎么调整?

   (1)查看年轻代内存是不是大小?

   (2)查看是否内存泄露问题。

   (3)打印gc log查看是否出现promotion failed 和concurrent mode failure,其中promotion failed是因为在进行Minor GC时,survior space 空间不足,放不下,会直接拷贝到老年代,同时老年代也放不下则会发生,则是因为执行CMS GC是有对象需要放到老年代,但是老年代放不下也会执行FULL GC。

1.13.红黑树有哪些特点?

   (1) 根节点必定是黑色;

   (2) 每一个节点不是红色就是黑色;

   (3) 如果节点是红色,则子节点必定是黑色;

   (4) 不能出现2个连续的红色节点;

   (5) 从根节点到叶子节点(包括空节点)的每条路径都必须包含相同数目的黑色节点;

   (6) 如果叶子节点是空节点(NIL)节点,则节点是黑色的。

1.14.JVM的内存模型?

JVM内存模型分为5个区域:

   (1)程序计数器:线程私有,无并发问题,唯一一个不会报error的区域;

   (2)本地方法栈:线程私有,无并发问题,可能会抛出StackOverFlowError和OutOfMemoryError错误;

   (3)JAVA虚拟机:线程私有,没有并发的问题,可能会抛出StackOverFlowError和OutOfMemoryError错误;

   (4)方法区:线程共享,有并发问题可能会抛出OutOfMemoryError错误;

   (5)堆:线程共享,有并发问题,可能会抛出OutOfMemoryError错误。

1.15.有三个线程T1、T2、T3,如何保证他们按顺序执行?

   在T1的run中,调用T1.join,让T1执行完成后再让T2执行;

   在T2的run中,调用T2.join,让T2执行完成后再让T3执行;

   Thread中的join函数的作用是让父线程等待子线程结束后才能继续运行。

1.16.CPU使用率过高怎么处理?

   (1)使用TOP命令找出使用率过高的PID;

   (2)然后在使用 top -p pid,单独查看,并且按住H找出使用具体使用资源率高的线程id,并且转换为16进制待用;

   (3)使用jstack ID打印堆栈信息,找到占满cpu的代码,再检查具体原因,再做调整。

1.17.HTTP协议的格式?

   (1)第一部分:第一部分只有一行格式为:请求类型+空格+请求地址+http协议名称和版本 例如:POST /user/list.html HTTP/1.1

   (2)第二部分:从第二行起为请求部分,请求为key:value的出现

   例如:Host:www.abc.com

​    Upgrade-Insecure-Request:1

   Accept:text/html

   (3)第三部分:第三部分为请求体,请求头与请求体之间用空行分隔,请求体通常为POST请求中的body内容。

1.18…线上发送频繁full gc怎么处理?

   频繁Full GC一般因为执行Minor GC后内存仍然不够用导致,所以我们可以开启。

   -XX:HeapDumpBeforeFullGC和-XX:+HeapDumpAfterFullGC参数在执行Full GC 前后打印一下内存使用情况,在结合一些分析工具(jvisualm),查看执行Full GC 的原因。

1.19.什么是线程池?

   线程池是帮助我们管理线程的,达到线程的重复使用,避免创建大量的线程增加开销的一种处理方法。

   一般情况下,一个线程池拥有:

   (1)队列:存放等待执行的任务;

   (2)工作线程:真正执行的线程;

   (3)线程管理器:(ThreaPoolManager):用于创建和管理线程池

   (4)任务接口(task)每个任务必须实现的接口,以便工作线程调度任务的执行。

1.20.为什么要用线程池?

   避免频繁创建和销毁线程达到线程对象的重用,另外使用线程池可以根据项目灵活控制并发的数目。

1.21.Runnable接口Callable接口有什么区别?

   Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地执行run()方法中代码而已;

   Callable接口中的call()方式是有泛型指的,是一个泛型,和future、FytureTask配合可以用来获取异步执行的结果。

1.22.wait()与sleep()有什么区别?

   sleep()方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,等时间结束线程进入就绪状态和其他线程一起竞争cpu的执行时间但是它“不释放锁”;

   wait()方法是Object类的一个方法,当类调用这个方法时,对象就会进入到一个与该对象相关的等待池,同时“释放锁”然后通过notify()、notifyAll方法来唤醒等待的线程。

1.23. notify()、notifyAll有什么区别?

   都是唤醒在等待的线程,notify只能唤醒单个线程,其他的线程继续等待,而noitfyAll唤醒所有等待被唤醒的线程。

   注意:notify()方法很容易发生死锁,除非你根据自己的程序设计,确定不会发生死锁,notifyAll()方法则是线程安全的唤醒方式。

1.24.volatile关键字有什么作用?

   一个特殊的关键字,一般用来修改变量并且是多线程共享的变量,确保变量的值读在写之后发生,从而确保了变量在并发环境的可见性。

   volatile修饰的变量的写会立即刷新主存,volatile变量的读写会读主存中的新值。

注意:volatile并不能保证100%的线程安全,因为它值保证变量的可见性,无法保证对变量操作的原子性。

1.25.TheadLocal有什么作用?

   ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本。通过ThreadLoacal可以将对象的可见范围限制在同一个线程内。因为它的可见范围是同一个线程内,所以不存在线程不安全的问题。

   ThreadLoacal适用于每个线程需要自己独立的实例且实例需要在多个方法中被使用,也即变量在线程间隔离而方法或类间共享的场景。

1.26.线程与进程有什么区别?

   线程是一个进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。

1.27.final、finally、finalize三个关键字的区别?

   final是终态的,是一个修饰关键字,可以修改类,方法,属性。

   finally通常和try catch搭配使用,保证不管有没有异常,finally内的diam都能被执行,通常用来释放资源;

finalize是Object中的一个方法,子类可以重写finalize方式实现对资源的回收Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法。

1.28.this与super关键字的区别是什么?

   this代表调用该方法的当前对象,可以访问本类的方法,属性等;

   super代表当前对象的父类,可以访问父类的方法、属性等;

   注意:this和super不能用于static修改的变量、方法、代码块,因为this和super都是指的是当前对象的实例。

1.29.如果要重写一个对象的equals方法,还要考虑什么?

   重写一个对象equals方法,还需要考虑到hashcode方法,系统没强制必须同时重写,不重写会报错,这样的强制措施,是约定:

   (1)无论何时,对同一个对象调用hashcode都应该生成同样的值;

   (2)如果两个对象根据equals方式是不相等的,那么调用这个两个中任一个对象的hashcode方法,不要求必须产生不同的整数结果。然而,程序员应该意识到这样的事实,对于不相等的对象产生截然不同的整数结果,有可能提高散列表(hashtable)的性能;

所以一般情况下相等的实例应具有相等的散列码。

1.30.线程调用了start()方法之后是立即执行么?

   不是的,调用了start方法只是告诉系统这个线程已经准备就绪了,可以被cpu执行了,具体什么时候执行是不确定,可以设置优先级,优先级高的被先执行的概率大,但是也不保证会立马被执行。

   注意:cpu会随机选择准备就绪的线程进行执行。优先级只能确定被随机的概率大!

1.31.可以直接调用线程的run()方法么?

   不可用,如果非要直接调用,就以普通的方法被执行,而不是开启一个线程去执行。

1.32.final关键字可以修改哪些地方,分别有什么效果?

   可以修饰类,被final修饰的类不能被继承;

   可以修改变量,被final修改的变量只能赋值一次,赋值后不可修改,如果是引用类型则不能修饰其引用;

   可以修饰常量,被修饰的方法不可被重写。

注意:private()会被隐式地被指定为final方法。
  

1.33.线程有几种状态?

   线程一种有6种,分别是:

   new:先创建,还没有调用start方法;

   runnable:准备就绪,调用start方法;

   blocked:阻塞状态,等待资源或锁或其他原因导致的线程阻塞时;

   waitting:等待状态,例如:wait方法是timed_waiting限时等待,例如调用了wait并且设置了等待时间的terminated结束,线程正常执行完成后。

1.34.Git中怎么把一个提交(commit)也同步提交到另一个分支?

   (1)使用 git log命令找到上一次提交的commit id;

   (2)切换到需要被提交的分支上;

   (3)在使用 git cherrcy-pick[commit-id]就可以把对应的提交同时提交到对应分支。

2. 并发题型
2.1.什么是公平锁?什么是非公平锁?举几个例子?

(1)公平锁

   线程获取不到锁的时候,会自动加入等待队列,等待线程释放后,队列的第一个获取线程锁,获取锁的顺序是按照加入队列的先后顺序获取 new ReentrantLock(true)创建的就是公平锁。

(2)非公平锁

   线程获取不到锁的时候,会自动加入等待队列,等待线程释放后,会通知队列的所有线程,然后所有线程一起竞争锁,所以可能会导致的结果就是有些线程一直抢不到锁。

2.2.sychronized关键字加在static方法和在普通方法上有什么区别?

   加在static方法上锁住的是该对象的Class对象,而加在普通方法上锁住的是当前对象的当前实例。

   如果一个对象里面既有synchronized static方法,又有synchronized methd普通方法当静态的加锁方法已经被一个线程持有了,那么另外一个线程可以获取普通方法上的锁吗?

   答案是可以,因为他们是2把锁,分别被2个线程获取,不会产生死锁,也不会等待。反过来也一样,当普通方法的锁被线程持有,另外一个线程照样能够成功获取静态方法上的锁。

2.3.什么是AQS原理?说说你的理解?

   AQS是指AbstractQueuedSynchronizer它是一个抽象的抽象队列同步器,是并发包的一个基础组件,它内部包含了一个int类型的state变量默认为0,一个当前加锁的线程变量,还有一个等待队列。

   一般的锁就是通过cas去设置state值为1标识加锁线程,如果当前锁已被其他线程获取则进入等待队列,当线程释放锁则是吧state改回0当前加锁线程变量设置为null并通知等待队列中的线程去获取锁。

   ReentrantLock 就是AQS的一种实现,因为他是可以重入的,所以当重入的时候是把state + 1释放是把state-1直到0表示完全释放锁,通知其他线程获取锁。

2.4.如果让你设计一个高可用系统,你需要考虑哪些方面?

   高可用系统设计到很多方面

   1、数据库,读写分离,分库分表,加索引

   2、加缓存,二级缓存,本地缓存+ Redis

   MQ解耦异步通知削峰(主要针对并发写的情况)因为并发读的情况由redis缓存解决-

   4、业务拆分不同业务独立部署—

   5、增加ES分布式查询系统。

   6、分担搜索业务流量。

2.5.Servlet是线程安全吗?

   单例多线程,本质是一个伪单例!不是线程安全的。Servlet是单例的tomcat接到连接请求时会从线程池中取一个线程执行,线程在找到对应的Servlet的时候如果没有初始化会先调用init()方法初始化,然后调用 service(),方法处理请求。

2.6.并发场景下数据库和缓存一致性的解决方案?或者说修改操作是先更新缓存还是先更新数据库?

   更新时先在redis中标记有更新操作在进行中。

   更新时可以先删除缓存再更新数据库

   更新完数据库再添加缓存其他现在在获取数据之前先校验是否有更新操作如果有则等待(加超时时间)更新完成后先从缓存获取,如果缓存获取不到则去数据库获取,在放入缓存。

2.7.如何实现接口的幂等性?

   在业务请求之前先更具业务特性生成一个token(UUID),并且校验token是否已经处理过了比如订单号,每次请求携带token标识,处理完成后标记token已处理。

2.8.什么是可重入锁(RentrantLock)?

   答:重入锁指的是在某一个线程中可以多次获得同一把锁,在线程中多次操作有锁的方法

2.9.什么是死锁?发生死锁的条件是什么?

   死锁是指两个或两个以上的进行在执行和过程中,由于竞争的资源或者由于彼此通信而造成一种阻塞的现象,如无外力作用,他们都无法推进下去。此时称系统处于死锁状态或者系统产生了死锁,这些永远在相互等待的进程称为死锁进程。

   产生死锁必须同时满足以下四种条件,只要其中任一条件不成立,死锁就不会发生!

   互斥条件:进程要求对所分配的资源(如打印机)进行排他控制,即在一段事件内某资源仅有一个进程所占有。此时如有其他进程请求资源,则请求进程只能等待;

   不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强制所占有,此时若有其他进程请求该资源化,则请求进程只能等待;

   请求和保持条件:进程已保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放;

   循环等待条件:存在一种进程资源的村换等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。

2.10.一个线程运行时发生异常怎么样?

   答:如果该异常被捕获或抛出,则程序继续运行。

   如果异常没有被捕英该线程将会停止执行。

   Thread.UncaughtExceptionHandler是用于处理未捕预异常造成线程突然中断情况的一个内 接口。当一个未捕获异常将造成线程中断的时候JVM会使用Thread.getuncaughtExceptionHandlero)来查询线程的UncaughtExceptionHandler,并将线程和异常作为参数传递handler的uncaughtException()方法进行处理。

2.11.Java中如何停止一个线程?

   答:Java中没有提供停止一个线程的api在早期版本中提供的 stop()suspend()resume()方法由于存在一些潜在的死锁问题在后续版本中被停用如果想手动结束线程,可以增加一个volatie boolean类型的变量,然后在在run()方法中增加校验该变量来结束执行(return),终止线程

2.12.如果实现一个流程程序,用户控制请求的调用次数?

   答:Semaphore信号量,Semaphore管理一系列许可证,每个acquire()方法阻塞,直到有一个许可证可以获得然后拿走一个许可证;每个release()方法增加一个许可证,这可能会释放一个阻塞的acquire()方法。然而其实并没有实际的许可证这个对象,Semaphore只是维持了一个可获得许可证的数量

2.13.Java如何实现原子操作?

   在JAVA中可以通过锁和循环CAS的方式来实现原子操作。

2.14.volatile和synchronized分别是怎么实现数据同步的?

   答:volatile是一个轻量级的锁,保证了共享变量的“可见性"不会引起线程上下文的切换和调度,volatiie.修饰的变量线程不会单独存取他的副本,每次需要使用是都是从主内存中读取,并且修改后悔立即刷辨到主内存,从而保证了线程同步synchronized则是快用内置锁来保证数据的同步的。

   1、加在普通同步方法,锁是当前实例对象

   2、加在静态同步方法,锁是当前类的class对象

   3、加在同步方法块,锁是括号里面的对象

2.15.如何实现乐观锁?如何避免ABA问题?

   答:CAS是乐观锁技术,当多个线程程,试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都关败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

   CAS操作中包含三个操作数-需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置v的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B否则处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。

可以使用只增补减的版本号来避免ABA的问题

2.16.CyclicBarrier和CountDownLatch有什么区别?

   答:CountDownLatch,允许一个或多个线程,等待其他一组线程完成操作,再继续执行。

   只能使用一次CyclicBarrier允许一组线程相互之等待,达到一个共同点,再继续执行。

   调用reset()重置状态,可以重复使用他们都是一个同步的辅助类

2.17.简述JDK1.8中CountDownLatch有什么区别?

简述jdk1.8中的ConcurrentHashMap原理

   答:ConcurrentHashMap底层使用数组+链表+红黑树来实现的,当链表长度达到8,转到红黑树结构,不过在转换之前会先判断table数组长度,如果小于默认值64,则会优先扩容table数组2倍长度来缓解链表过长问题。jdk1.8中放弃了Segment的分段锁设计,取而代之的是采用Node+CAS+Synchronized来保证并发安全进行实现;在第一次执行put方法时才会调用initTable()初始化Node数组,如果插入Node位置为空。则使用cas的方式插入数据,如果Mode位置已经有数据了则使用syschronized(当前node)增加数据,如果节点是TreeBin(红黑树)结构则使用putTree()方法加入。

2.18.什么是悲观锁?什么是乐观锁?

   悲观锁是指如果一个线程占用了一个锁,而导致其他所需要这个锁的线程进入等待,一直到该锁被释放,换句话说就是这个锁被占用,比如典型的就是synchronized;

   乐观锁是指操作并不加锁,而是抱着尝试的态度去执行某项操作,如果操作失败或者操作冲突,那么就进入充实,一直到执行成功为止。

3. 框架题型
3.1.Spring是如何解决循环依赖问题的?

   构造器循环依赖,和Scope(bean作用域)为prototype的bean,无法解决循环依赖问题,会抛出BeanCurrentLyIn CreationException异常,单例类的bean(Scope=singleton)在创建的时候会先在已无参数构造函数创建bean,然后放入bean创建池中,在去创建之前会先检测创建池中是否存在正在创建中的bean如果存在则拿出来进行装配。

3.2.Spring Cloud Zuul过滤器怎么添加?

   继承ZuulFilter类,并且重写4个函数

   (1)filterType()过滤器的类型取值范围[pre,route,post,error]

​       Pre:可以在请求被路由之前调用;

​       Route:路由请求时被调用;

​       Post:在routing和error过滤器之后被调用;

​       Error:处理请求时发生错误时被调用;

   (2)FilterOrder()过滤器的执行顺序,数值越小优先级越高;

   (3)ShouldFilter()过滤器是否要执行。可以设置执行条件来校验;

   (4)Run()过滤器的过滤逻辑都写在这里。

3.3.Spring Cloud有哪些常用组件?

   (1)Eureku:注册中心

   (2)Config:配置中心

   (3)Feign:客户端工具

   (4)Ribbon:负载均衡

   (5)Hysrix:熔断器

   (6)Zuul:动态路由

3.4.Mybatis缓存是怎么回事?

   Mybatis有2级缓存,一级缓存是sqlSession级别的,默认开启,二级缓存是Mapper级别的,通过设置enableCache=true开启另外Mybatis缓存只要有DML操作就会清空缓存。

3.5Spring MVC工作流程?

   用户请求–DispatcheServlet(核心控制器)–HandlerMapping(处理映射器)–HandleAdapter(处理适配器)–Handel(处理器)–ViewResovler(视图解析器)–视图渲染–响应用户

3.6.SpringIOC实现原理?

   通过动态代理实现,动态代理有2中方式:

      (1)jdk动态代理,需要实现特点的接口

      (2)Cglib动态代理,无需实现任何接口

3.7.SpringBoot实现自动配置(AutoCongiguration)的原理?

   当我们的项目开启了自动配置的注解@EnableAutoConfiguration后项目启动后会自动的扫描子项目,拿到META-INF/spring,factories文件,找到相应的配置类,并进行相应的配置

3.8.Sping事务的传播性有哪些?

   有7种:

   表示当前方法必须进行在事务中,如果当前事务存在,方法将会在该事物中进行,否则,会自动开启一个新的事物;

   表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事物中进行;

   表示当前方法必须在事物中运行,如果当前事务将不存在,则会抛出一个异常;

   表示当前方法必须运行在它自己的事务中,一个4新的事物将被启动,如果存在当前事务,在该方法执行期间,当前事务会被挂起;

   表示当前方法不应该运行在事物中,如果存在当前事务,在该方法运行期间,当前事务将被挂起;

   表示当前方法不应该运行在事务上下文,如果当前正有一个食物在运行,则会抛出一个异常;

   表示当前已经存在一个事物,那么该方法将会在嵌套事务中运行,如果当前事务不存在,那么其行为与(1)一样

3.9.@Autowired @Resource @Qualifer三个注解有什么区别?

   @Autowired是Spring的注解,只能按照类型注入,可以设置required是否为空;

   @Resource是JDK的注解,默认按照名称注入指定name,则会按照名称注入,如果指定type则按照类型注入,如果指定了则必须都匹配才能注入

   @Qualifer是Spring的注解,按照名称注入,不可单独使用,单独使用无法注入会报空指针异常,需要配合@Autowired使用

3.10.Sping的注入方式有几种?

   三种:

   1、构造器注入,通过构造函数注入

   2、Set方法注入,通过set方法注入

   3、接口注入:注入的bean必须实现对应的接口

4.中间件题型
4.1.Zookeeper有什么作用?

   Zookeeper是分布式协调系统,具体用处:

   (1)配置管理:集中式配置管理,不容易丢失,不会遗漏,修改后立即生效等好处,可以针对不同环境设置不同配置

   (2)注册中心(名字服务):通过分布式项目名称类获取真实的ip端口等,服务器宕机或者下线可以删除

   (3)分布式锁:提高分布式环境的可靠性

   (4)集群管理:分布式环境中的SOA服务治理

4.2.kafka是如何做到高可用的?

   kafka中同一个Topic分片存储(多个Partition)实现并行处理,另外kafka中还有副本同步策略,同一个消息会备份多份,多个副本之间有一个Leader多个Follower

4.3.Dubbo注册中心挂掉后可以继续通信吗?

   都挂掉之后可以依赖本地缓存继续通信,但是无法注册新的服务

4.4.kafka是如何保证消息的有序性?

   在发送消息的时候指定partition或者key应为kafka能保证同一个partition(分片)的消息是有序的,如果指定了key则保证相同的key会发往同一个partition

4.5…Dubbo在Spring2.x初始化死锁怎么回事?

   在Spring解析到dubbo:service时,就已经向外暴露了服务,而spring还在接着初始化其他bean,如果这时有请求进来,并且服务的实现类里有调用applicationContext.getBean()的用法。getBean()线程和sping初始化线程的锁的顺序不一样,导致线程死锁,不能提供服务,启动不了。不要在服务的实现类中使用applicationContext.getBean();如果不想依赖配置顺序,可以将dubbo:provider的deplay属性设置为-1,使dubbo的容器初始化完成后再暴露服务。

4.6.Dubbo有哪些负载均策略?

   Dubbo提供了4负载均衡器策略:

   (1)RandomLoadBalance基于权重随机算法

   (2)LeastActiveLoadBalance最少活跃调用数算法

   (3)ConsistentHashLoadBalance hash一致性调用算法

   (4)RoundRobinLoadBalance加全轮询算法

4.7.Dubbo支持哪些协议?

   dubbo://

   Dubbo 协议官方推荐的协议,缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。

   rmi://

   RMI协议采用JDK标准的java.rim.*实现,采用阻塞式短连接和JDK标准序列化方式。

   Hessian://

   Hession协议用于集成Hessian的服务,hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现。

5.存储题型
5.1.Redis怎么获取一个有过期时间的剩余时间?

   一般这个命令使用的比较少,但是在面试中可能会被问到,所以稍微记一下

   ttl当key不存在时,返回-2,当key存在但没有设置剩余生存时间时,返回-1,否则【以秒】为单位返回key的剩余时间

   Pttl当key不存在时,返回-2,当key存在但没有设置剩余生存时间,返回-1,否则以【毫秒】为单位返回key的剩余时间

5.2.Redis具体可以用来存储哪些数据?

   1、热点数据,例如,一般首页整页的数据都放缓存

   2、分布式Session解决方案(cookie+redis)

   3、整表数据缓存(使用hash结构)

   4、简单的分布式(list结构实现) 延时队列(sorted set,时间戳当score)

5.3.数据库的分表策略?

   1、横线划分:某一种表的属性太多,可以拆分出来2张表,一张表保存数据(需要经常修改),一张表保存冷数据(查询较多)

   2、表单数据量过大,达到表单上线,需要水平拆分,拆分原则有:

   Range:从0到10000一个表,10001到20000一个表

   Hash:取模,例如id%表容量

   地理区域:比如按照华东,华南,华北这样来区分业务

   时间:就是将6个月前,甚至是一年前的数据切出去放到另一张表,因为随着时间的流逝,这些表的数据被查询的概率变小,所以没必要和“热数据”放在一起,这个也是“冷热数据分离”

5.4.分布式事务怎么实现的?

   分布式事务一般分为2种:

   1、二阶段提交

   事务参与者向协调者发送确认请求(提交或回滚),当协调者收到参与者都同意提交之后,则给所有参与者发送提交信息,否则发送回滚信息

   2、三阶段提交

第一阶段:can_commit(准备)协调者先发送请求给参与者询问是否可以执行

   事务,参与者给出预估回答

   第二阶段:pre_commit(预提交)协调者更具第一阶段返回值判断是否会向所有参与者发送事务执行请求,如果第一阶段全部返回确定消息,则发送提交请求

   第三阶段:do_commit(提交阶段)如果第二阶段都返回正确消息,则向参与者发送commit,提交信息并且等待参与者反馈信息

5.5.说说Redis的哨兵模式?

   Redis-Sentinel是官方推荐的高可用解决方案。

   它的主要功能有一下几点

      1、Redis集群的监控

      2、如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端)

      3、如果master挂掉能够自动切换,选举出一个slave来代替master物Sentinel

   的工作方式:

​    Sentinel的工作方式

      1、每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他Sentinel实例发送一个PING命令

      2、如果一个实例(instance)距离最后多次有效回复PING命令的时间超过down-after-milliseconds选项所指定的值,则这个实例会被Sentinel标记为主观下线

      3、如果一个Master被标记为主观下线,则正在较监视这个Master的所有Sentinel要以每秒一次的频率确认Master的确进入了主观下线状态。

      4、当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线

      5、在一般情况下,每个Sentinel会以每10秒一次的频率向它已知的所有Master,SLave发送INFO命令

      6、当Master被Sentinel标记为客观下线时,Sentinel向下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次

      7、若没有足够数量的Sentinel同意Master已经下线了,Master的客观下线状态就会被移除。若Maser重新向Sentine的PING命令返回有效返回,Master的主观下线状态就会被移除

5.6.数据库索引新建原则有哪些?

   1、具有唯一性的属性必须增加唯约束,与唯一索引。

   2、经常出现在where子句中的查询条件需要增加索引3、如果属性为大文本不要增加索引4、字符串类型的索引需要指定长度,尽量使用前缀来早增加索引5、经常会被join联合查询的外键需妥增加索引6、一张表不要增加太多索引7、索引尽量增加在区分度比较高的属性上。

   (例如:性别属性一般不是男就是女区分度不高,但是年龄区分读相对比较高,在比如,创建时间属性,区分度更高,基本每行数据时间都不一样。)8、不经常使用,或很少使用的索引需要删除

5.7.Mysql如何解决主从同步延时问题?

   1、从库设置sync-binlog =8让系统觉得什么时候同步到磁盘innodb-flush_logattrx_commit设置为0,或2(0延迟写,然后实时刷新到硬盘, 2实时写延迟刷新到硬盘,1实时写,实时刷到硬盘。

   2、提高从库的硬件性能

   3、提高数据版本到mysql 5.6.3以上,支持多线程同步

5.8.Mysql数据库主从同步延迟原理?

   MySQL主库的DDL(数据库表结构改变sqL)和DML(数据的增删改操作)会产生binLog日志,从库读取主库的binlog然后在从库实施,从库的同步线程(SLave-SL_Running)是单线程,如果其中一个执行卡主了,后面的操作都会等待,造成延迟。

   另外还有就是可能同步操作和slave的大型query语句产生了锁等待

5.9.Redis支持的数据类型有哪些?

   String:普通的key-value存储

   Hash:String类型的field和value的映射表

   Set:无序不重复的集合

   List:简单的字符串列表,有序的集合

   Sorted Set:有序的不可重复的集合СAM

5.10.Redis分布式锁怎么实现?

   使用setnx命令同时加上过期时间,以当前请求ID为value(释放锁的时候可以校验是否是当前持有者防止其他线程无意中释放了锁)

   Long result =jedis.setnx(lockKey,requestId,expireTime);;

   Return result == 1;

   还可以增加重试次数

   Int max =10;

   for(;max>0;max–){

   Long result =jedis.setnx(lockkey ,requestId,exprieTime)

   If(result ==1){

   return true;}

   Tread.sleep(30);

   }

   return false;

5.11.Redis集群模式有那几种?

   主要有2中:

      1、主从集群,主要是为了高可用或是读写分离,单向链表结构,master宕机,salve可以自动切换为master

      2、分布式集群,数据分片存储,扩展单机内存上限,网状结构,

5.12.Redis持久化存储与方式有哪几种?

   二种

   1、RDB方式,定期保存的内存快照,适合大规模的数据恢复,但它的数据一致性和完整性较差。

   2、AOF方式,将写操作日志追加到AOF文件中,数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。定期重写AOF文件,压缩文件大小。

5.13.left join和right join、inner join有什么区别?

   Left join 以左表为主,显示左表的全部数据

   right join 以右表为主,显示右表的全部数据

   Inner join 则显示2张表的所有数据

5.14.索引有B索引和hash索引,有什么区别?

   Hash索引,等值查询效率高,不能排序,不能进行范围查询

   B+数据有序,可进行范围查询

5.15.数据库的事务隔离级别有哪些?

   答:数据库的隔离级别有4级分别是:

   读为提交 --脏读问题

   读已提交 --不可重复读问题

  重复读 --幻读问题

  串行化 --无

5.16.事务的特征有哪些?

  1、原子性:要么执行,要么不执行

  2、隔离性:所有操作全部执行完之前,其他会话不能看到过程

  3、一致性:事务前后,数据总额前后

  4、持久性:一旦事物提交,对数据的改变就是永久的

5.17.什么样的属性适合创建索引?

  唯一、不为空、经常被查询的字段。

5.18.Redis 内存淘汰策略有哪些?

  1、noevication:当内存不足时,新写入操作会报错;

  2、allkeys-lru:当内存不足时,随机移除一些Key;

  3、Allkeys-randam:当内存不足时,随机移除一些Key;

  4、Volatile-lru:当内存不足时,在设置了过期时间的key中移除最近最少使用的Key

  5、Volatile-random:当内存不足时,在设置了过期时间的Key中随机移除某些Key

  6、Volatile-ttl:当内存不足时,在设置了过期时间的key中移除即将过期的Key

5.19.Redis Key的过期策略有哪些 ?

  1、惰性删除:键过期了就过期了,不管。每次从dict字典中按key取值时,先检查此key是否过期,如果过期了就删除它,并返回nil,如果没过期,就返回键值。

  2、定时删除,每隔一段时间,对expires字典进行检查,删除里面的过期键。

5.20.Mysql中的列值为NULL时,查询是否会用到索引?

  在MySQL里Null值的列也是走的索引的,不过如果列添加了索引,最好不要使用Null值,因为MySQL无法优化空值列的查询,它会使索引、索引统计和值更加复杂。另外只要列涉及到运算,MySQL就不会使用索引。例如

  Where year(createDate)<2019,就不会走索引。

5.21.Mysql存储引擎中的InnoDB和MyISAM的区别?
InnoDBMyISAM
支持事务不支持事务
数据存储在共享表空间数据存储在文件中
支持行级锁只支持行级锁
支持崩溃后的恢复不支持崩溃后的恢复
支持外键不支持外键
不支持全文索引支持全文索引

5.22.Mysql中的varchar和char的区别是什么?Float和double的区别是什么?

  Varchar 的长度是动态的,会随着你的存入内容而调整。

  Char 的长度是固定的。如果你的内容是固定大小的,你会得到更好的性能。

  Float 类型数据可以存储至多8位十进制数,并在内存中占4字节

  Double 类型数据可以存储至多16位十进制数,并在内存中8占字节


  ☝上述分享来源微信小程序“疯狂刷题-JAVA”,如有侵权,请联系本人,我会立即进行删除!
  如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!

☞本人博客:https://coding0110lin.blog.csdn.net/  欢迎转载,一起技术交流吧!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/324018
推荐阅读
相关标签
  

闽ICP备14008679号