CSDN学院年终倾情奉献,海量Java面试题免费提供,持续更新的第七辑,10道面试题,主要涉及:单点登录实现,消息列队,以及几种代理模式等内容,感谢大家的支持。
Java工程师常见面试题集锦(一)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/85602533
Java工程师常见面试题集锦(二)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86138938
Java工程师常见面试题集锦(三)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86471513
Java工程师常见面试题集锦(四)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86525565
Java工程师常见面试题集锦(五)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86591005
Java工程师常见面试题集锦(六)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86638413
如果觉得文字学习较慢,也可以跟着老师一起视频学习:
Java面试题视频学习链接:https://edu.csdn.net/course/detail/10533
61.Elasticsearch 和 solr 的区别
背景:它们都是基于Lucene搜索服务器基础之上开发,一款优秀的,高性能的企业级搜索服务器。【是因为他们都是基于分词技术构建的倒排索引的方式进行查询】
开发语言:java语言开发
诞生时间:
Solr :2004年诞生。
Es:2010年诞生。
Es 更新【功能越强大】
区别:
1)当实时建立索引的时候,solr会产生io阻塞,而es则不会,es查询性能要高于solr。
2)在不断动态添加数据的时候,solr的检索效率会变的低下,而es则没有什么变化。
3)Solr利用zookeeper进行分布式管理,而es自身带有分布式系统管理功能。Solr一般都要部署到web服务器上,比如tomcat。启动tomcat的时候需要配置tomcat与solr的关联。【Solr 的本质 是一个动态web项目】
4)Solr支持更多的格式数据[xml,json,csv等],而es仅支持json文件格式。
5)Solr是传统搜索应用的有力解决方案,但是es更适用于新兴的实时搜索应用。单纯的对已有数据进行检索的时候,solr效率更好,高于es。
6)Solr官网提供的功能更多,而es本身更注重于核心功能,高级功能多有第三方插件。
62.单点登录实现过程
单点登录:一处登录多处使用!
前提:单点登录多使用在分布式系统中。
Demo:
参观动物园流程:
检票员=认证中心模块
1)我直接带着大家进动物园,则会被检票员拦住【看我们是否有门票】,没有[售票处买票]
登录=买票
2)我去买票【带着票,带着大家一起准备进入动物园】检票员check【有票】
Token=piao
3)我们手中有票就可以任意观赏动物的每处景点。
京东:单点登录,是将token放入到cookie中的。
案例:将浏览器的cookie禁用,则在登录京东则失败!无论如何登录不了!
63. 消息队列在项目中的使用
背景:在分布式系统中是如何处理高并发的。
由于在高并发的环境下,来不及同步处理用户发送的请求,则会导致请求发生阻塞。比如说,大量的insert,update之类的请求同时到达数据库MYSQL,直接导致无数的行锁表锁,甚至会导致请求堆积很多。从而触发 too many connections 错误。使用消息队列可以解决【异步通信】
1)异步
2)并行
3)排队
4)消息队列电商使用场景
消息队列的弊端:
消息的不确定性:延迟队列,轮询技术来解决该问题即可!
推荐大家使用activemq!环境都是java。
64. 单例模式
单例就是该类只能返回一个实例。
单例所具备的特点:
1)私有化的构造函数
2)私有的静态的全局变量
3)公有的静态的方法
单例分为懒汉式、饿汉式和双层锁式
饿汉式:
public class Singleton1 {
private Singleton1() {};
private static Singleton1 single = new Singleton1();
public static Singleton1 getInstance() {
return single;
}
}
懒汉式:
public class Singleton2 {
private Singleton2() {}
private static Singleton2 single=null;
public tatic Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
线程安全:
public class Singleton3 {
private Singleton3() {}
private static Singleton3 single ;
public static Singleton3 getInstance() {
if(null == single){
synchronized(single ){
if(null == single){
single = new Singleton3();
}
}
}
return single;
}
}
参考:
通过双重判断来保证单列设计模式在多线程中的安全性,
并且它在性能方面提高了很多。
synchronized在方法上加锁 (同步锁)
synchronized在代码块内部加锁 (同步代码块)
synchronized(同步锁)
使用synchronized如何解决线程安全的问题?
1)synchronized在方法上加锁
2)synchronized在代码块内部加锁
1)懒汉 2)饿汉 3)双重判断
65.什么是代理模式
代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:
66.为什么要使用代理模式
1)中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
2)开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
67.有哪几种代理模式
我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。
静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。
动态代理是在程序运行时通过反射机制动态创建的。
68.观察者模式
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个 ArrayList 存放者们。
优点:1)观察者和被观察者是抽象耦合的。 2)建立一套触发机制。
缺点: 1)如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2)如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
69.适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
如何解决:继承或依赖(推荐)。
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
优点:1)可以让任何两个没有关联的类一起运行; 2)提高了类的复用; 3)增加了类的透明度; 4)灵活性好。
缺点:1)过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构;2)由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
70.命令模式
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。
关键代码:定义三个角色:1)received 真正的命令执行对象 ;2)Command ;3)invoker 使用命令对象的入口
应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。
优点:1)降低了系统耦合度2)新的命令可以很容易添加到系统中去。
缺点:使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景:认为是命令的地方都可以使用命令模式,比如: 1)GUI 中每一个按钮都是一条命令; 2)模拟 CMD。
注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。
Java工程师常见面试题集锦(一)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/85602533
Java工程师常见面试题集锦(二)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86138938
Java工程师常见面试题集锦(三)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86471513
Java工程师常见面试题集锦(四)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86525565
Java工程师常见面试题集锦(五)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86591005
Java工程师常见面试题集锦(六)互联网人必看!https://blog.csdn.net/CSDNedu/article/details/86638413
如果觉得文字学习较慢,也可以跟着老师一起视频学习:
Java面试题视频学习链接:https://edu.csdn.net/course/detail/10533