(根据自己的面试经验总结的知识点,内容比较浅显,有问题的地方欢迎指正呀)

三、前端部分

3.1、简单说一下html,css,javascript

HTML 超文本标记语言 定义网页的结构
CSS 层叠样式表,用来美化页面
JavaScript主要用来验证表单,做动态交互(其中ajax)

3.2、简单介绍一下Ajax?

  1. 什么是Ajax?
    异步的javascript和xml
  2. 作用是什么?
    通过AJAX与服务器进行数据交换,AJAX可以使网页实现布局更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  3. 怎么来实现Ajax XmlHttpRequest对象?
    使用这个对象可以异步向服务器发送请求,获取获取响应,完成局部更新。Open send responseText/responseXML 局部响应.
  4. 使用场景?
    登陆失败时不跳转页面,注册时提示用户名是否存在,二级联动等等使用场景

3.3、 js和jQuery的关系?

jQuery是一个js框架,封装了js的属性和方法。让用户使用起来更加便利。,并且增强了js的功能.
使用原生js是要处理很多兼容性的问题(注册事件等),由jQuery封装了底层,就不用处理兼容性问题。
原生的js的dom和事件绑定和Ajax等操作非常麻烦,jQuery封装以后操作非常方便。

3.4、 jQuery的常用选择器?6个

  1. ID选择器 通过ID获取一个元素
  2. Class选择器 通过类(css)获取元素
  3. 标签选择器 通过标签获取元素
  4. 通用选择器(*) 获取所有的元素
    div.myCls 获取有myCls这个类的div
  5. 层次选择器
    儿子选择器 > 获取下面的子元素
    后代选择器 空格 获取下面后代,包括儿子、孙子等后代
  6. 属性选择器
    Tag[attrName=’test’] 获取有属性名为xxxx并且属性的值为test的所有xxx标签
    吃饭

3.5、 jQuery的页面加载完毕事件?

很多时候我们需要获取元素,但是必须等到该元素被加载完成后才能获取。我们可以把js代码放到该元素的后面,但是这样就会造成js在我们的body中存在不好管理。所有页面加载完毕后所有的元素当然已经加载完毕。一般获取元素做操作都要在页面加载完毕后操作。

  1. 第一种:(document).ready(function());(document).ready(function(){});(document):
    把原生的document这个dom对象转换为jQuery对象,转换完成后才能调用ready方法ready(fn),表示的是页面结构被加载完毕后执行传入函数fn
  2. 第二种:$(function(){});当页面加载完毕后执行里面的函数
    这一种相对简单,用得最多window.onload的区别jQuery中的页面加载完毕事件,表示的是页面结构被加载完毕。

3.6、 Jquery的Ajax和原生Js实现Ajax有什么关系?

jQuery中的Ajax也是通过原生的js封装的。封装完成后让我们使用起来更加便利,不用考虑底层实现或兼容性等处理。
如果采用原生js实现Ajax是非常麻烦的,并且每次都是一样的。如果我们不使用jQuery我们也要封装Ajax对象的方法和属性。有像jQuery这些已经封装完成,并经过很多企业实际的框架,比较可靠并且开源。我们就不需要封装,直接使用成熟的框架(jQuery)即可.

3.7、简单说一下html5?你对现在的那些新技术有了解?

Html5是最新版本的html,是在原来html4的基础上增强了一些标签。
Html增加一些像画板、声音、视频、web存储等高级功能。但是html5有一个不好的地方,那就是html5太强调语义了,导致开发中都不知道要选择那个标签。
在做页面布局是,无论头部、主题、导航等模块都使用div来表示,但是html5的规范,需要使用不同的标签来表示。(header footer等)

3.8、 简单说一下css3?

Css3是最新版本的css,是对原理css2的功能增强。
Css3中提供一些原来css2中实现起来比较困难或者不能实现的功能。
1、盒子圆角边框
2、盒子和文字的阴影
3、渐变
4、转换 移动、缩放、旋转等
5、过渡、动画都可以使用动画。
6、可以使用媒体查询实现响应式网站。
Css3最大缺点就是要根据不同的浏览器处理兼容性。对应有一些处理兼容性的工具。不用担心.

3.9、 Bootstrap是什么?

BootStrap是一个移动设备优先的UI框架。我们可以不用写任何css,js代码就能实现比较漂亮的有交互性的页面。我们程序员对页面的编写是有硬伤的,所有要自己写页面的话就要使用类似于bootstrap这样的UI框架。平时用得很多的:模态框\表单,表单项\布局\删格系统

四、 设计模式

4.1、讲一下什么是设计模式?常用的设计模式有哪些?

设计模式就是经过前人无数次的实践总结出的,设计过程中可以反复使用的、可以解决特定问题的设计方法。

  1. 单例(饱汉模式、饥汉模式)
    (1)构造方法私有化,让出了自己类中能创建外其他地方都不能创建
    (2)在自己的类中创建一个单实例(饱汉模式是一出来就创建创建单实例,而饥汉模式需要的时候才创建)
    (3)提供一个方法获取该实例对象(创建时需要进行方法同步)
  2. 工厂模式:Spring IOC就是使用了工厂模式, 对象的创建交给一个工厂去创建。
  3. 代理模式:Spring AOP就是使用的动态代理。
    常用的设计模式有:单例模式、工厂模式、观察者模式、适配器模式、亨元模式等。

4.1.1、单例模式代码

  1. 饿汉式单例:(立即加载)
    // 饿汉式单例public class Singleton1 {
    // 指向自己实例的私有静态引用,主动创建
    private static Singleton1 singleton1 = new Singleton1();
    // 私有的构造方法
    private Singleton1(){}
    // 以自己实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton1 getSingleton1(){
    return singleton1;
    }
  2. 懒汉式单例:(延迟加载)
    // 懒汉式单例public class Singleton2 {
    // 指向自己实例的私有静态引用
    private static Singleton2 singleton2;
    // 私有的构造方法
    private Singleton2(){}
    // 以自己实例为返回值的静态的公有方法,静态工厂方法
    public static Singleton2 getSingleton2(){
    // 被动创建,在真正需要使用时才去创建
    if (singleton2 == null) {
    singleton2 = new Singleton2();
    }
    return singleton2;
    }

4.1.2、单例模式应用场景

  1. 以下都是单例模式的经典使用场景:
    1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
    2.控制资源的情况下,方便资源之间的互相通信。如线程池等。
  2. 应用场景举例:
    1.外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件
    2. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~
    3. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
    4. 网站的计数器,一般也是采用单例模式实现,否则难以同步。
    5. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
    6. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
    7. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
    8. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
    9. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
    10. HttpApplication 也是单位例的典型应用。熟悉ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例.

4.3、Synchronized介绍(比较基础)

4.3.1、作用

同步方法支持一种简单的策略来防止线程干扰和内存一致性错误,如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。即:能够保证在同一时刻最多只有一个线程执行该段代码,达到保证并发安全的效果。Synchronized是Java的关键字,被Java原生支持。最基本的互斥同步手段。

4.3. 2、用法

对象锁
方法锁(锁对象为this当前实例对象)
同步代码锁(自己指定锁对象)
类锁:只有一个Class对象
synchronized修饰静态方法
指定锁为Class对象

4.3.3、多线程访问同步方法的7种情况

1、两个线程同时访问一个对象的同步方法​ 串行执行
2、两个线程访问的是两个对象的同步方法并行方法,不是一个对象。
3、两个线程访问的是synchronized的静态方法串行执行,只有一个Class对象
4、同时访问同步方法和非同步方法​ 串行执行
5、访问同一个对象的不同的普通同步方法串行,this是同一个
6、同时访问静态synchronized和非静态的synchronized方法并行执行,锁对象不是同一个
7、方法抛出异常后,释放锁synchronized会自动释放,Lock等不会

4.3.4、 三个核心思想

一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应第1、5种情况)
每个实例都对应有自己的一把锁,不同实例之前互不影响;例外:锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象共用同一把类锁(对应2、3、4、6种情况)
无论是方法正常执行完毕或者方法抛出异常,都会释放锁(对应第7种情况)

4.3.5、性质

1、可重入:同一个线程的外层函数获取锁后,内层函数可以直接再次获取该锁。
2、不可中断

4.3.6、原理

1、加锁和释放锁的原理:Monitor
2、可重入原理:加锁次数计数器
3、可见性原理:内存模型图

4.3.7、缺点

1、效率低
锁的释放情况少
视图获取锁时不能设置超时时间
不能中断一个正在视图获取锁的线程
2、灵活度较差
加锁和释放锁的时机单一
每个锁仅有单一的对象
3、无法知道是否成功获取到锁

4.3.8、注意点

1、锁对象不能为空、作用域不宜过大、避免死锁
2、尽量使用JUC包下的类,再考虑Synchronized,再考虑Lock

五、JVM

5.1、JVM内存模型

根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
Java高频面试题(三)

  1. 程序计数器(线程私有):是当前线程锁执行字节码的行号治时期,每条线程都有一个独立的程序计数器,这类内存也称为“线程私有”的内存。正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果是Natice方法,则为空。
  2. java 虚拟机栈:也是线程私有的。每个方法在执行的时候也会创建一个栈帧,存储了局部变量,操作数,动态链接,方法返回地址。每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。通常所说的栈,一般是指在虚拟机栈中的局部变量部分。局部变量所需内存在编译期间完成分配,如果线程请求的栈深度大于虚拟机所允许的深度,则StackOverflowError。如果虚拟机栈可以动态扩展,扩展到无法申请足够的内存,则OutOfMemoryError。
  3. 本地方法栈(线程私有):和虚拟机栈类似,主要为虚拟机使用到的Native方法服务。也会抛出StackOverflowError 和OutOfMemoryError。
  4. Java堆(线程共享):被所有线程共享的一块内存区域,在虚拟机启动的时候创建,用于存放对象实例。对可以按照可扩展来实现(通过-Xmx 和-Xms 来控制)当队中没有内存可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
  5. 方法区(线程共享):被所有方法线程共享的一块内存区域。用于存储已经被虚拟机加载的类信息,常量,静态变量等。这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。

5.2、JVM调优原因

对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数

  1. Full GC:会对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比较慢,因此应该尽可能减少Full GC的次数。
  2. 导致Full GC的原因
    1)年老代(Tenured)被写满:调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象 。
    2)持久代Pemanet Generation空间不足:增大Perm Gen空间,避免太多静态对象 , 控制好新生代和旧生代的比例
    3)System.gc()被显示调用:垃圾回收不要手动触发,尽量依靠JVM自身的机制

5.3、JVM调优方法和步骤

  1. 监控GC的状态:使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化。
    举一个例子: 系统崩溃前的一些现象:(1)每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也由之前的0.5s延长到4、5s;(2)FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC;(3)年老代的内存越来越大,并且每次FullGC后年老代没有内存,被释放之后系统会无法响应新的请求,逐渐到达OutOfMemoryError的临界值,这个时候就需要分析JVM内存快照dump。
  2. 生成堆的dump文件:通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件。
  3. 分析dump文件:打开这个3G的堆信息文件,显然一般的Window系统没有这么大的内存,必须借助高配置的Linux,几种工具打开该文件:
    Visual VM
    IBM HeapAnalyzer
    JDK 自带的Hprof工具
    Mat(Eclipse专门的静态内存分析工具)推荐使用
    备注:文件太大,建议使用Eclipse专门的静态内存分析工具Mat打开分析。
  4. 分析结果,判断是否需要优化:如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化,如果GC时间超过1-3秒,或者频繁GC,则必须优化。
    注:如果满足下面的指标,则一般不需要进行GC:
    Minor GC执行时间不到50ms;
    Minor GC执行不频繁,约10秒一次;
    Full GC执行时间不到1s;
    Full GC执行频率不算频繁,不低于10分钟1次;
  5. 调整GC类型和内存分配:如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找1台或几台机器进行beta,然后比较优化过的机器和没有优化的机器的性能对比,并有针对性的做出最后选择。
  6. 不断的分析和调整:通过不断的试验和试错,分析并找到最合适的参数,如果找到了最合适的参数,则将这些参数应用到所有服务器。

5.4、GC root有几下种:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象
  2. 方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中JIN(一般说的Native方法)引用的对象
  5. Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,
  6. Thread - 活着的线程
  7. Stack Local - Java方法的local变量或参数
  8. JNI Local - JNI方法的local变量或参数
  9. JNI Global - 全局JNI引用
  10. Monitor Used - 用于同步的监控对象

相关文章: