第一篇

JAVA知识

1.java的四个基本特性,对多态的理解
  • java的四个基本特性
    • 继承:继承是从已有的类得到继承信息创建新类的过程,提供继承信息的类被称为父类
    • 抽象:抽象时间一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象
    • 封装:通常认为封装是吧数据和操作数据的方法绑定起来,对数据的访问只能通过一定义的接口
    • 多态:允许不同子类型的对象对同一消息作出不同的响应
  • 多态的理解
    • 方法的重载:实现的是编译时的多态(前绑定)
    • 方法的重写:实现的是运行时的多态(后绑定)
    • 实现的多态需要做的两件事:1.方法重写(子类继承父类并重写父类中已有的或抽象方法)2.对象造型(用父类型应用一用自类型的引用)
  • 项目中多态的应用
    • 简单例子:在物流信息管理系统中,有两种用户:订购客户和卖房客户,登录系统都用Login,但是Login里面的东西不同

 

  深层次的挖掘-> https://www.cnblogs.com/chenssy/p/3372798.html  多态的面试题解析(一定要记住)

          https://blog.csdn.net/clqyhy/article/details/78978785 同上

 

2.面向对象和面向过程的区别
  • 面向对象和面向过程的区别
    • 面向过程就像一个细心的管家,事无巨细都要考虑到,二面向对象就像是个家用电器。只要知道功能,不需要知道他的工作原理
    • 面向过程是时间为中心的编程思想,就是分析出解决问题所需要的步骤,然后用函数将这些步骤实现,并按照顺序调用,面向对象是一对象为中心的编程思想
 
3.重载和重写
  • 重载:重载放生在同一个类中,同名的方法如果有不同的参数列表(参数类型不同,参数个数不通过,或者二者都不同),则视为重载
  • 重写:重写发生在子类和父类之间,重写要求子类被重写方法与父类被重写的方法有相同的返回类型,,比父类被重写方法更更好访问,不能比父类被重写方法声明更多的异常(历史替换原则),根据不同的子类对象确定调用哪个方法。

 

4.面对对象开发的六个基本原则(面试中问过)
  • 六个基本原则
    • 单一职责:一个类只做他该做的事情(高内聚:面向对象中,如果只让一个类完成它该做的事,而不设计与他无关的领域就是践行了高内聚)
    • 开放封闭:软件尸体应当对扩展开放,对修改封闭。要做到开闭有两个要点:1.抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点2.封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统就变的复杂而混乱
    • 里氏替换原则:任何时候都可用子类型替换掉父类型,子类一定是增加父类的能力而不是减少父类的能力,因此子类比父类的能力更多,把能力多的对象换能力少的对象当然没有任何问题
    • 依赖倒置:面向接口编程(该原则说的直白和具体一些就是生命方法的参数类型,方法返回类型,变量的引用类型事,尽可能用抽象类型而不用具体类型,因为抽象类型可以被他的任何子类所代替)
    • 合成聚合复用:优先使用聚合或合成关系复用代码(不要直接使用继承-容易破坏开闭原则)
    • 接口隔离:接口小而专,绝不能大而全,一个接口应该只描述一种能力,接口也应该是高内聚的。
  • 迪米特法则:又称最少知识原则,一个对象应该对其他对象有尽可能少的了解
  • 项目中用到的原则:单一职责,开放封闭,合成聚合复用(String?),接口隔离

 

5.static,final的区别和用途
  • static
    • 修饰变量:静态变量随着类加载时被完成初始化,内存中只有一个,但jvm也只会为它分配一次内存,所有类共享静态变量
    • 修饰方法:类加载的时候就存在,不依赖任何的实例,static方法必须实现,不能用abstract
    • 修饰代码块:在类加载完之后就会执行代码块中的内容
    • 父类静态代码块->子类静态代码块->父类非静态代码块->父类构造方法->子类非静态代码块->子类构造方法
  • final
    • 修饰变量
      • 编译期常量:类加载的过程完成初始化,编译后带入到任何计算式中也能是基本类型
      • 运行时常量:基本数据类型饮用数据类型,引用不可变,但是引用的对象内容可变
    • 修饰方法:不能被继承,不能被子类修改
    • 修饰类:不能继承
    • 修饰形参:final形参不可变

 

6.HashMap和Hashtable的区别,HashMap中的key可以是任何对象或数据类型么?Hashtable是线程安全的么?
  • HashMap和Hashtable的区别
    • Hashtable的方法是同步的,HashMap未经同步,所以多线程的时候要手动同步
    • Hashtable不允许NULL值(key和value都不可以),HashMap允许NULL值(key和value都可以)
    • 两者的遍历方式大同小异,Hashtable比HashMap多了elements方法,Hashtable和HashMap都能通过values返回Collection,然后遍历,两者都可以返回entrySet,然后遍历处理
    • Hashtable使用Enumeration,HashMap使用Iterator
    • 哈希值的使用不同,Hashtable直接使用对象的hashcode,而HashMap重新计算hash值,而且用&代替求模运算
    • Hashtable的hash数组默认大小是11,增加方式是old*2+1 ,HashMap的hash数组默认大小是16,而且必须是2的指数
    • Hashtable给予Dictionary类,而HashMap给予AbstractMap类
  •  HashMap中的key可以是任何对象或数据类型么
    • 可以为NULL,但不能是可变对象,如果是可变对象的话,对象中的属性改变,则对象hashcode也进行相应的改变,d无法查找到map中的数据
    • 如果可变对象在HashMap中作为键,那就要小心在改变对象状态的时候不要改变他的哈希值了,需要保证Hash值不变即可
  • Hashtable是线程安全的么
    • Hashtable是线程安全的,其实是在对应的方法上添加了synchronized关键字进行修饰,优于执行侧方法的时候需要获取到对象的锁,但是运行起来非常的慢为了实现线程安全,使用ConcurrentHashMap

 

7.HashMap和ConcurrentHashMap的区别,ConcurrentHashMap是线程安全的么?ConcurrentHashMap如何保证线程安全?(面试问过,一定要多看几遍,这个是重点)
  • HashMap和ConcurrentHashMap的区别
    • HashMap非线程安全,ConcurrentHashMap线程安全
    • ConcurrentHashMap将整个Hash桶进行了分段Segment,也就是将这个大的数组分成了集合小的片段segment,而且每个小的片段segment上都有锁的存在,那么在插入元素的时候就需要小找到应该插入的那一个片段segment,然后在这个片段进行插入,畏怯这里还要获取segment锁 (JDK7)
    • ConcurrentHashMap让所得力度更精细一些,并发性能更好
  • ConcurrentHashMap线程安全么,ConcurrentHashMap如何保证线程的安全
    • Hashtable在竞争激烈的并发环境下变现出效率低下是因为都必须竞争一把锁,假如容器里又多把锁,每一把锁用于所容器的一部分数据,那么当多线程发昂问容器里的不同数据时,线程就不会有锁的竞争,从而提高兵法访问效率,这就是ConcurrentHashMap锁使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段数据也能被其他线程访问
    • get操作的搞笑指出在于整个get过程不需要加锁,除非是读到空值才会加锁重读,get方法里将使用的共享变量都定义成volatile,如用于统计当前Segemnt大小的count 字段,用于存储值的HashEntry的value,定义成volatile的变量能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(写入不依赖原值除外)
    • put方法首先定位带segment然后在segment里进行插入操作,插入操作需要经历两个步骤,第一步判断segment里的HashEntry是否需要扩容,第二部定位到HashEntry然后插入数据(JDK7)

  todo 拓展HashMap源码

 

8.因为别人知道远吗怎么实现,故意构造相同的hash的字符串进行攻击怎么处理?那jdk7怎么办?
  • 怎么处理构造相同的hash字符串进行攻击
    • 当客户端提交一个请求并附带参数的时候,web应用服务器会把我们的参数化成一个HashMap存储,这个HashMap的逻辑结构如下:key->value
    • 但是物理存储结构是不同的,key值会化成hashcode,这个hashcode会被转成数组下标:0->value1
    • 不同的String会产生相同的hashcode而导致碰撞,结构0->value1->value2
    • 限制post和get的参数个数,越少越好
    • 限制post数据包的大小
    • WAF
  •  jdk7如何处理hashcode字符串攻击
    • HashMap会动态的使用一个专门的treemap实现来替换掉它
9.String,StringBuffer,StringBuilder以及对 String 不可变的理解(面试问过,当时没回答出来String不可变的设计)
  • 都是final类型,都不允许被继承
  • String的长度是不可变的,StringBuffer,StringBuilder的长度是可变的
  • StringBuffer是线程安全的,StringBuilder不是线程安全,他们的方法都是一样的,StringBuffer的所有方法都添加了synchronized修饰,保证线程安全
  • StringBuilder比StringBuffer有更好的性能
  • 如果一个String类型的字符串,在编译时就可以确定是一个字符串常量,到编译完成之后,字符床会自动拼接成一个常量,此时string的速度比StringBuffer,StringBuilder要快
  • String不变性的理解
    • String类是被final进行修饰的,不能被继承
    • 用+连接字符串的时候会创建新的字符串
    • String s = new String("hello") 可能会创建两个对象也可能创建一个对象,如果静态区中有“hello”字符常量对象的话,则仅仅在堆中会创建一个对象,如果静态区中没有的话就需要创建两个对象,也就是字符串池的优化需要,多次创建字符串只会返回同一个对象
    • 在java中通过使用“+”拼接字符的话,底层会转成通过StringBuilder实力的append方法来实现
    • 保证配置环境的安全性

 

10.String有重写Object的hashcode和toString么?如果重写equals不重写hashcode会出现什么问题?
  • String有重写Object的hashcode和toString方法么
    • String重写了hashcode和toString方法
  •  当equals方法被重写时,通常有必要重写hashcode方法,以维护hashcode方法的常规协定,该协定声明相等的两个对象必须有相同的hashcode
    • object1.equals(object2)为true,object1.hashcode()==object2.hashcode()为true
    • object1.hashcode()==object2.hashcode()为false,bject1.equals(object2)为false
    • object1.hashcode()==object2.hashcode()为true,bject1.equals(object2)为不一定为true

  很容易举出的例子就是HashMap的key的hashcode

11.Java序列化,如何实现序列化和反序列化,常见的序列化协议有哪些?

 

12.java实现多线程的方式及各自的区别?
  • 实现多线程的三种方式
    • 继承Thread类,重写run函数
    • 实现Runnable接口
    • 实现Callable接口
  •  三种方式的区别
    • 实现Runnable可以避免java单继承所带来的局限,增强健壮性,代码数据相互独立
    • 继承Thread类和实现Runnable方法启动线程都是使用start方法,然后jvm虚拟机将此线程放到就绪队列中,有处理机可用,则执行run方法
    • 实现Callable接口要实现call方法,并且线程执行完会有返回值,其他两种没有返回值

 

13.线程安全
  • 定义
    • 某个类的行为与其规范一致
    • 不管多个线程是怎样执行顺序和优先级,或是wait,sleep,join等控制方式,如果一个类在多线程访问下运转一切正常,并且访问不需要额外同步处理或者协调,那么我们就认为他是线程安全的
  • 如何保证线程安全的
    • 对变量使用volatile
    • 对程序段进行加锁synchronized   

  

  • 注意
    • 非线程安全的集合在多线程环境下可以使用,但不能作为多线程共享的属性,可以作为莫线程独享的属性
    • 例如Vector是线程安全的,ArrayList不是线程安全的,如果每一个线程中new一个ArrayList,而这个ArrayList只是在这个线程中使用,肯定没有问题

 

14.多线程如何进行信息交互(面试问过,当时回答的不全)
  • object中的方法,wait(),notify(),notifyAll()
  • 通过共享内存的方式,定义一个volatile变量,两个线程轮训处理这个变量

 

15.多线程共用一个数据变量需要注意什么?
  • 当我们在线程对象(Runnable)中定义了全局变量,run方法会修改该变量时,如果有多个线程同时使用该线程对象,那么就会在城全局变量的值被同时修改,造成错误
  • ThreadLocal是jdk引入的一种机制,它解决了线程间共享变量,使用ThreadLocal声明的变量,即时在线程中属于全局变量,针对于某个线程来讲,这个变量也是独立的
  • volatile变量每次被线程访问的同时,都强迫线程从驻内存中重新读区该变量的最新值,而当该变量发生修改变化的时候,会强迫当前线程将当前的最新值刷新到贮存,这样一来不同线程都能及时的看到该变量的最新值

 

16.什么是线程池?如何让你设计一个动态大小的线程池,如何设计,应该用哪些方法?
  • 什么是线程池
    • 线程池顾名思义就是实现创建若干个可执行的线程放入到池中,需要的时候从池中获取线程不用自省创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁对象的开销
  • 设计一个动态大小的线程池,如何设计,应该有哪些方法
    • 一个线程池包含以下四个基本组成部分
      • 线程管理器(ThreadPool):用于创建并管理线程池的,包括创建线程池,销毁线程池,添加新任务
      • 工作线程(PoolWork):线程池中的线程,在没有任务时处于等待状态,可以循环的执行任务
      • 任务接口(Task):每个任务必须实现的接口,一共工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等
      • 任务队列(TaskQueue):用于存放没有处理的任务,提供一种缓冲机制 
    • 所包含的方法
      • ThreadPool()创建线程池
      • getThreadPool()获得一个默认线程个数的线程池
      • execute(Runnable task)执行任务,其实只是把任务加入到任务队列,什么时候执行由线程池管理规定
      • execute(Runnable[] task)批量执行任务,同上
      • destroy()销毁线程池,该方法保证所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁

 

  todo 这里需要对线程池的源码进行一下解析

 

17.java是否有内存泄漏和内存溢出?
  • 静态集合类:使用Set,Vector,HashMap等集合类的时候规定,当哲学类被定义成静态的时候,由于他们的生命周期跟应用程序一样长,这个时候有可能发生内存泄漏
    •   
      class StaticTest{
        private static Vector v = new Vector(10);
        
        public void init(){
          for(int I = 0 ; I < 100;i++){
              Object object = new Object();
              v.add(object);
              object = null;
          }
        }        
      }

      上面代码中,循环创建了Object对象,并添加到Vector中,然后设置为null,可是这些对象被Vector饮用者,因此不能被GC回收,因此造成了内存泄漏,因此要释放这些对象,还需要将他们从vector中删除,最简单的方法就是将Vector设置为null

  • 监听器:在Java编程中,我们都需要和监听器打交道,通常一个程序中会用到很多监听器,但是在释放的时候没有去删除这些监听器,从而增加了内存泄漏的机会
  • 物理连接:一些物理连接,比如数据库连接和网络连接,除非是显示的关闭了连接,否则是不会自动被GC回收的,java数据库谅解一般用datasource.getConnection()来创建,当不再适应必须用close()方法释放,因为这些连接时独立于JVM的,所以需要在try-catch-finally中释放连接
  • 单例模式:因为单例对象初始化后在jvm的整个生命周期内存在,如果他持有一个外部对象的引用(生命周期比较短),那么这个外部对象就不能回首,从而导致内存泄漏,如果这个外部对象还持有其他对象的引用,那么内存泄漏更严重

 

 

18.concurrent包下面都用过什么(面试问过)
  • concurrent下面的包
    • Executor用来创建线程池,实现Callable接口,添加线程
    • FutureTask此FutureTask的get方法所返回的结果类型
    • TimeUnit
    • Semaphore
    • LinkedBlockingQueue
  • 所用过的类
    • Executor 

 

19.volatile关键字如何保证内存可见性(面试问过)
  • volatile关键字的作用
    • 保证内存的可见性
    • 防止指令重拍
    • 注意:volatile不保证原子性
    内存可见性
    • volatile保证可见性的原理是在每次访问变量时都会进行一次刷新,因此每次访问都是主内存中最新的版本,索引volatile关键字的作用之一就是保证变量秀高的实时可见性 
    当且仅当满足以下所有条件是,才应该使用volatile
    • 对变量的写入不依赖变量的当前值,或者你能确保只有当个线程更新变量的值
    • 该变量没有包含在具有其他变量的不变式中
    volatile使用建议
    • 在两个或者更多的线程需要访问的成员变量上使用volatile,当要访问的变量已在synchronized代码扩种或者卫敞亮,没必要使用volatile
    • 优于使用volatile屏蔽掉了jvm的必要的的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字
    volatile和synchronized的区别
    • volatile不会进行加锁操作,volatile是一种稍弱的同步机制在访问colatile变量是不会进行加锁操作,因此就不会执行线程阻塞,因此volatile变量是一种比synchronized更轻量级的同步机制
    • volatile变量的作用类似于同步变量的读写操作:从内存可见性角度来看,写入volatile变量相当于推出同步代码块,而读取volatile变量相当于进入同步代码块
    • volatile不如synchronized安全,在代码中如果过度依赖volatile变量来控制状态的可见性,通常会比使用锁的代码更加脆弱,也更难以理解,仅当volatile变量能简化代码的实现一机对同步策略的验证时,才应该适应它,一般来说,使用同步机制会更加安全一些
    • volatile无法保证内存可见性和原子性,加锁机制(同步机制)既可以保证可见性又可以保证原子性,而volatile变量只能保证可见性,原因是生命为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作 count++,count = count+1

 

 

20.sleep和wait分别是哪个类的方法
  • sleep和wait
    • sleep是thread类的方法
    • wait是object的方法
  • 有什么区别
    • sleep方法(休眠)是线程类的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自定恢复(线程回到就绪状态)
    • wait()是object的方法,调用对象的wait方法导致当前线程放弃对象的锁(线程暂停执行),进入到对象的等待池中,只有调用对象的notify方法才能唤醒等待池中的线程到对象等锁池中,如果线程重新获得对象的锁就可以进入就绪状态 

 

21.synchronized和lock的区别(面试问过)
  • synchronized与lock的区别
    • synchronized(隐式锁):在需要同步的对象中架次控制,synchronized科技加载方法上也可以加载代码块中,括号中表示需要的锁的对象
    • lock(显示锁):需要制定起始的位置和中止的位置,一般使用ReentrantLock类作为锁,多个线程必须使用一个ReentrantLock类作为锁,且加锁和解锁必须指出lock()和unlock(),一般会在finally中些unlock防止死锁
    • 性能上synchronized是托管给jvm的,lock是java写的控制锁的代码,在1.5中synchronized性能低消,1.6以后做了优化,有适应性自旋,缩小出,锁粗话,轻量级锁,偏向锁等,并不比lock差
    • 机制上synchronized原始采用的是CPU悲观锁,即线程独占锁,独占锁一位置其他线程只能依靠阻塞来等待线程释放锁,Lock用的是乐观锁方式,如果冲突就重试,直到成功,乐观锁的实现机制就是CAS操作。

 

22.synchronized的底层是如何实现的(面试问过)
  • 底层实现:https://blog.csdn.net/javazejian/article/details/72828483   java虚拟机中的同步给予进入和退出管程(Monitor)对象实现,无论是显示同步有明确的monitorenter和monitorexit指令,即同步代码块,还是隐形的同步,同步方法并不是有指令实现的而是由方法的ACC_SYNCHRONIZED实现的,注意1.6以后的synchronized的优化-偏向锁,轻量级锁,自旋,锁清除等
  • 用在代码块和方法上有什么区别
    • synchronized用在代码块锁调用的是该方法的对象,也可以选择锁住任何一个对象
    • synchronized用在方法上锁的是调用该方法的对象
    • synchronized用在代码块可以减小锁的力度,从而提高兵法性能
    • 无论用在代码块上还是用在方法上,都是获取对象的锁,每一个对象只有一个锁与之冠良,实现同步需要很大的系统开销作为代价,甚至可能造成死锁,所以尽量避免无所谓的同步控制

 

23.常见的异常分那两种?常见异常的积累以及常见的异常(概念模糊)
  • Throwable是java语言中所有错误和异常的超类,他有两个子类:Error,Exception
  • 异常种类
    • Error:程序无法处理比如OutOfMemory,ThreadDeath等,出现这种情况只能由jvm处理,jvm大多数情况袭会选择终止线程
    • Exception:Exception是程序可以处理的异常,他又分为受检查异常和不受检查异常
      • 不受检查异常:发生在运行时期,具有不确定性,由程序逻辑引起的比如NullPorinterException
      • 受检查异常:发生在编译阶段,必须使用try-catch(或者throws),否则编译不通过

 

24.java的NIO,BIO,AIO分别是什么(很重要的概念,一定要了解)
  •  BIO
    • 同步并阻塞,服务器实现为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
    • BIO方式适用于连接数小而且固定的架构,这种方式对服务器资源要求比较高,兵法句小雨应用中,jdk1.4的唯一选择,程序简单理解
  • NIO
    • 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都归注册到多路复用器上,多路复用器轮训到连接有I/IO请求,才请求一个线程处理
    • NIO方式适用于连接数目多且连接比较短(轻操作),比如聊天服务器,兵法局限于应用中,编程比较负载,jdk1.4开始支持  
  • AIO
    • 异步非阻塞,服务器实现模式为一个有效的请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程处理
    • AIO方式适用于连接数目过多且连接比较长(重操作),比如相册服务器,充分利用OS参与兵法操作,编程比较复杂7以后才支持

 

 

25.所了解的设计模式,单例模式的注意事项,jdk源码用到了哪些设计模式(个人觉得也是非常重要的概念)
  • 所了解的设计模式
    • 工厂模式:定义一个用于创建对象的接口,让子类决定是梨花哪一个类,factory method是一个类的是梨花延迟到子类
    • 单例模式:保证一个类只有一个示例,并提供一个访问他的全局访问点
    • 适配器模式:将一类的接口转换成客户希望的另一个接口,adapter模式是的原本不兼容而不能一起工作的那些类可以一起工作
    • 装饰者模式:动态地给一个对象增加一些额外的职责,就增加功能来说,Decorator模式相比于孜勒更加的灵活
    • 代理模式:为其他对象提供一种代理一控制这个对象的访问
    • 迭代器模式:提供一个方法顺序访问一个聚合对象的哥哥元素,而又不暴露该对象的内部表示
  •  单例模式的注意事项
    • 尽量使用懒加载
    • 重重检索实现线程安全(double-check)
    • 构造方法为private
    • 定义静态的singleton instance对象和getInstance方法
  • jdk源码中用到的设计模式
    • 装饰者模式:I/O流
    • 迭代器模式:Iterator
    • 单例模式:Runtime
    • 代理模式:RMI 

  todo 设计模式一定要多了解  

 

26.匿名内部类是什么?如何访问在其外面定义的变量
  • 匿名内部类是什么
    • 您名内部类是是没有访问修饰符的
    • 所以当所在方法的形参需要被匿名使用,那么这个形参就必须为final
    • 匿名内部类没有构造方法,因为他连名字都没有
  •  如何访问在外面定义变量
    •  必须定义为final

 

27.如果你定义一个类,包括学好,姓名,分数没如何把这个对象作为key?要重写equals和hashcode么?
  • 需要重写equals和hashcode方法,必须保证对象的属性改变时hashcode不变 

 

28.为什么要实现内存模型(不是JVM,是JMM很重要,面试可能会问)
  • 内存模型就是为了在现代计算机平台中保证程序可以正确性的整形,但是不同平台的实现时不同的
  • 编译器中生成的指令顺序可以与源代码中的顺序不同
  • 编译器可以吧变量保存在寄存器中而不是内存中
  • 处理器可以采用乱序或并行等方式来执行指令
  • 缓存可能会改变将写入变量提交到主内存的次序
  • 保存在处理器本地缓存中的值对其他处理器是不可见的

 

数据库知识

 

1.常用的数据库有哪些?redis用过么?
  • 常用的数据库
    • mysql,sqlServer
  • redis
    • redis是一个速度非常快的非关系性数据库,他可以存储建雨5中不同类型的值,可以讲存储在内存中的简直数据持久化到磁盘中
    • 与memcached相比
      • 两者都可用于存储键值映射,彼此性能也相差无几
      • redis能够自动以两种不同的方式将数据写入硬盘
      • reids除了能存储普通的字符串之外,还可以存储其他四种结构,memcached只能存储字符串
      • redis既能用做主数据库,又可以作为其他存储系统的辅助数据库

 

2.数据库索引的优缺点以及是么时候数据库索引失效(面试问过)
  • 索引的特点
    • 可以加快数据库检索的速度
    • 降低数据库插入,修改,删除等维护的速度
    • 只能创建在表上,不能创建在视图上
    • 既可以直接创建又可以间接创建
    • 可以在优化隐藏中使用索引
    • 使用查询处理器执行sql语句,在一个表上,一次只能使用一个索引
  • 索引的优点
    • 创建唯一性索引,保证数据库中每一行数据的唯一性
    • 大大加快数据检索速度,这是创建索引的主要原因
    • 加快数据表之间的连接,特别是在实现数据的参考完整性方面有特别的意义
    • 在使用分组和排序子句进行数据检索是,同样可以显著减少查询中分组和排序的时间
    • 通过使用索引,可以在查询中使用优化隐藏起,提高系统的性能
  • 索引的缺点
    • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
    • 索引需要占用物理空间,除了数据表占用数据空间之外,每一个索引还要占一定的物理空间,如果简历聚簇索引需要的空间就会更大
    • 当对应的表数据进行增加,删除和修改的时候,索引也需要维护,降低数据维护的速度
  • 索引的分类
    • 直接创建索引和间接创建索引
    • 普通索引和唯一性索引
    • 单个索引和复合索引
    • 聚簇索引和非聚簇索引
  • 索引失效
    • 如果条件中有or,即时其中有条件带来索引也不会使用
    • 对于多列索引,不是使用的第一部分,则不会使用索引
    • like查询是一%开头的
    • 如果列类型是字符串,那一定要在条件中用引号引起来,否则不会使用索引
    • 如果mysql估计使用全表嫂面壁使用索引快,则不使用索引
  • 各引擎支持的索引
    • 略过了

 

3.事务的隔离级别(这个概念很重要)
  • 读未提交
    • 最低的隔离级别,允许其他食物看到没有提交的数据,会导致脏读
  • 读已提交
    • 被读取的数据可能被其他事物修改了,这样可能导致不可重复读,也就是说,是武都区的时候获取锁,但是再度娃之后立刻释放(不需要等待十五结束),而写锁则是事务提交之后才释放,释放毒素哦之后就可能被其他事务修改数据,该等级也是sqlServer默认的隔离等里
  • 可重复读
    • 所有被select修改过的数据都不能被修改,这样可以避免一个事物前后读不一致的情况,但是没办法控制幻读,因为这个时候其他事务不能更改所选的数据,但是可以新增数据,因为该事务没有范围锁
  • 串行化
    • 所有事物一个接着一个的被执行,这样就可以避免幻读,对于给予锁来实现兵法控制的数据库来说,串行化要求在执行范围查询的时候,需要获取范围锁,如果不是给予锁实现并发控制的数据库,则检查有违反串行操作的食物,则需要回滚事务
隔离界别脏读不可重复度幻读 
读未提交可能可能可能 
读已提交不可能可能可能 
可重复读不可能不可能可能 
串行化不可能不可能不可能 

 

 

4.数据库中的范式(概念薄弱,需要注意)
  • 目前关系型数据库有六种范式:第一范式,第二范式,第三范式,巴斯克等范式,第四范式,第五范式,一般来说满足第三范式就足够了
  • 范式
    • 1NF:每个属性都不可再分
    • 2NF:属性完全依赖与主键(消除部分子函数依赖)
    • 3NF:属性不依赖于其他非主属性
    • BCNF:任何非主属性不能对主键子集依赖
    • 4NF:要求同一表内的多对多关系删除
    • 5NF:从最终结构重新建立原始结构

 

5.数据库中的索引结构?什么情况下适合建索引

  • 数据库中的索引结构
    • 因为在使用二叉树的时候由于二叉树的深度过大而造成I/O读写过于频繁,进而导致查询效率低下,因此采用多茶树结构,B树的各种操作能是B树保持较低的高度
  • B树又叫平衡多路查找树,一个m阶的B树特性如下:
    • 树中的每个节点最多含有m个孩子(m>=2)
    • 除了根节点和叶子节点外,其他每个节点至少有[ceil(m/2)]个孩子(其中ceil(x)是取上限的函数)
    • 根节点至少有两个孩子
    • 所有叶子节点都出现在同一层,叶子节点不包含任何关键字信息
  • B+树
  • 在什么情况下适合建立索引
    • 为经常出现在关键字order by,group by,distinct后面的字段,建立索引
    • 在union等集合操作的结果,建立索引,其建立索引的目的同上
    • 为经常用做查询选择字段,建立索引
    • 为经常用做表连接的属性上建立索引
    • 考虑使用索引覆盖,对数据很少被更新的表,如果用户进场只查询其中几个字段,可以考虑在这几个字段上建立索引,从而将表的扫面变为索引的扫描

 

6.redis的存储结构,或者说如何工作,与mysql的区别,有哪些数据类型(面试问过)
  • redis的数据结构
    • string:可以是整数,字符串,浮点数
    • list:一个链表,链表上的每个节点都包含了一个字符串
    • set:包含了字符串的无需收集器,并且被包含的字符串都是独一无二,各不相同的
    • hash:包含键值对的无序散列表
    • zset:字符串成员于浮点数之间的有序映射,元素的排列顺序有分值的大小决定

 

7.数据库中分页查询语句怎么写
  • mysql的limit用法
    • select from table limit offset ,size

 

8.数据库ACID(基本概念)
  • 原子性:保证事务中的所有操作全部执行或者全不执行
  • 一致性:保证数据库始终保持数据的一致性-事务操作之前和之后是一致的
  • 持久性:事务操作完成之后对数据库的影响是持久的,即便是市局哭因故障而受到破坏,数据库也能恢复
  • 隔离性:多个事务并发的时候结果应该是互不影响的,也就是结果应该与多个事务穿行执行结果一样的

 

9.脏读,不可重复读和幻读(也是基本概念)
  • 脏读:事务T1更新了一行记录,但是没有提交所做的修改,T2读取更新后的行,然后T1执行了回滚操作,取消了刚才所做的修改,现在T2读取的行就无效了
  • 不可重复读:事务T1读取一行记录,紧接着T2修改了T1刚才读取的一行记录,T1又再次读取这行记录,发现与刚才读取的结果不同
  • 幻读:事务T1读取一条指定的where子句所返回的结果,然后T2事务新插入一行记录,这行记录刚好可以满足T1所使用的查询条件,然后T1再次查询,发现多了一行

 

 

10.MyISAM和InnoDB引擎的区别(基本概念)
  • 主要区别
    • MyISAM是非事务安全性,而InnoDB是事务安全性
    • MyISAM锁的粒度是表级的,而InnoDB支持行级锁
    • MyISAM支持全文索引,InnoDB不支持
    • MyISAM相对简单,效率相对优于InnoDB
    • MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦
    • InnoDb表比ISAM表更安全,可以保证数据不会丢失的情况,切换非事务表到事务表
  • 应用场景
    • MyISAM管理非事务表,它提供高速存储和检索,如果应用中需要执行大量的select查询,那么MyISAM是更好的选择
    • InnoDB用于事务处理应用程序,具有众多特性,包括ACID事务的支持,如果应用中需要执行大量的insert,update,则应该使用Inn oDB

 

JAVA虚拟机

 

1.JVM垃圾处理方法
  • 标记-清除算法
    • 标记阶段:先通过根节点,标记所有从根节点开始的对象,未被标记的为垃圾对象
    • 清除阶段:清除所有未被标记的对象
  • 复制算法
    • 将原有的内存空间分为两块,每次只使用一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的呢村块中,然后清除正在使用的内存块中的所有对象
  • 标记-整理算法
    • 标记阶段:先通过根节点,标记所有从根节点开始的对象,未被标记的为垃圾对象
    • 整理阶段:将所有存活对象压缩到内存的一端,之后清理边界的所有空间
  • 三种算法的比较
    • 效率:复制算法=标记整理>标记清除
    • 内存整齐度:复制算法=标记整理>标记清除
    • 内存利用率:标记整理>标记清除>复制算法

 

2.JVM如何GC,新生代,老年代,持久代都存储哪些东西,以及各个区的作用
  •  新生代
    • 在方法中去new一个对象,那这方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象
  • 老年代
    • 在新生代中经历了N次来几回收后仍然存活的对象就会被放到老年代中,而且大对象直接进入到老年代
    • 当survivor空间不够用时,需要依赖于老年代进行分配担保,所以大对象直接进入老年代
  • 永久代
    • 即方法区

  担保机制需要深入了解一下   

 

3.GC用的引用可达性分析算法中,哪些对象可作为GC ROOTS的对象(重要概念)
  •  java虚拟机栈中的对象
  • 方法区中的静态对象
  • 方法区中的常量引用对象
  • 本地方法区中JNI(Native方法)引用对象

 

4.什么时候进行MinGC,FullGC
  • MinGC:
    • 新生代中的垃圾收集动作,采用的是复制算法
    • 对于较大的对象,在MinorGC的时候可以直接进入到老年代 
  • FullGC:
    • FullGC是发生在老年代的垃圾收集动作,采用的是标记清除/整理算法
    • 由于老年代的对象几乎都是Survivor区煎熬过老的不会那么容易死掉,因此FullGC触发的不是那么的频繁 

  这里感觉FullGC理解有误区,要重新学习

  什么时候触发FullGC请看这里

 

5.各个垃圾收集器是怎么工作的

  • Serial收集器
    • 是一个单线程收集器,不是只能使用一个CPU,在进行垃圾收集时,必须暂行其他所有的工作线程,知道收集结束
    • 新生代采用复制算法,stop-the-world
    • 老年代采用标记整理算法,stop-the-world
    • 简单高效,client模式下默认的新生代收集器
  • ParNew收集器
    • ParNew收集器时Serial收集器的多线程版本
    • 新生代采用复制算法,stop-the-world
    • 老年代采用标记整理算法,stop-the-world
    • 它是运行在server模式下的首选的新生代收集器
    • 除了serial收集器之外,只有他能和CMS收集器配合工作
  • ParNew Scanvenge收集器
    • 类似ParNew收集器,但更加关注吞吐量,目标是:达到一个可控制吞吐量的收集器
    • 停顿时间和吞吐量不可能同时调优,我们一方面希望停顿时间减少,另一方面希望吞吐量高,这是矛盾的,因为在GC的时候,来及回收工作总总量不变,如果停顿时间减少,那频率就会提高,既然频率提高了,说明就会进行GC吞吐量就会减少,性能会降低
  • G1收集器
    • 是当今收集器发展的最前沿成果之一,对垃圾回收进行了划分优先级的操作,这种优先级的区域回收方式保证了他的高效率
    • 最大的优点就是结合了空间整合,不会产生大量的碎片,也降低了进行gc的频率
    • 让使用者明确指定停顿时间
  • CMS收集器(兵法标记清除老年代收集器)
    • 一种以获得最短回收停顿时间为目标的收集器,适用于互联网站或者B/S系统的服务器
    • 初始标记(stop-the-world):跟可以直接关联到的对象
    • 并发标记(和用户线程一起):主要标记过程,标记全部对象
    • 重新标记(stop-the-world):由于并发标记,用户线程依然运行,因此在正式清理钱,在做修正
    • 并发清除(和用户线程一起):基于标记结果,直接清理对象
    • 并发收集,低停顿

 

 

6.Java虚拟机内存的划分,每个区域的功能
  • 程序计数器(线程私有)
  • 虚拟机栈(线程私有)
  • 本地方法栈(线程私有)
  • java堆
  • 方法区
  • 运行时常量池

 

 

7.用什么工具可以查出内存泄漏
  • MemoryAnalyzer
  • EclipseMAT
  • JProbe

 

 

8.JVM如何加载一个类的过程,双亲委派模型中,哪些方法有没有可能父类加载器和子类加载器同一个类,该使用哪一个类
  •  双亲委派概念
  • 加载器
  • 结果加载同一个类,该使用哪一个类

 

9.JVM线程死锁,你该如何判断是因为什么?如果用VisualVM,dump线程信息出来,会有哪些信息
  • 常常需要在个两分钟后在收集一次thread dump,如果得到输出结果相同,仍然是大量thread都在等待给同一个地址上上锁,那么肯定死锁了 

 

10.java是如何进行对象实例话的

 

 

11.Student s = new Student(),在内存中做了哪些事情?(流程了解一下)
  • 加载Student.class文件进内存
  • 在栈内为s开辟空间
  • 在堆内存为学生对象开辟空间
  • 为学生对象的成员变量进行默认初始化
  • 为学生对象的成员变量进行显示初始化
  • 通过构造方法为学生对象的成员变量赋值
  • 学生对象初始化完毕,把对象地址复制给s变量

 

 

12.了解JVM调优没,基本思路是什么(面试应该会问)

 

 

 

 

JSP和Servlet(这里有很多知识点要学一下)

 

1.保持会话状态,有哪些方式,区别如何?(这里也是重点)
  • 由于http协议本身是无状态的,服务器为了区分不同的用户,就需要对用户绘画进行跟踪,简单的说就是为了用户进行登记,为用户分配一个id,下次用户在请求中包含此id,服务器就会判断到底是哪一个用户
    • url重写:在url中添加用户绘画的信息作为请求的参数,或者将唯一会话的id添加到url结尾一标识一个绘画
    • 设置表单以藏于:将会话跟踪相关字段添加到隐式表单中,这些信息不会再浏览器中显示但是提交表单时会提交给服务器 
  • 这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改url活在页面中添加隐式表单来存储用户绘画相关信息,事情将会变的非常满帆  

 

2.cookie和session的区别(面试问过)
  • session存储在服务器端,cookie存储在客户端
  • session运行依赖sessionid,而sessionid存在cookie中,也就是说如果cookie禁用了,同时session也会失效
  • session可以放在文件,数据库,或者内存中
  • 用户验证这种场合一般会用session
  • cookie不是很安全,别人可以分析存放在本地的cookie并且进行cookie欺骗,考虑到安全应该使用session
  • session会在一定时间呗保存在服务器上,当访问增多,会比较占用服务器的性能考虑到减轻服务器的压力应当使用cookoe
  • 单个cookie不能超过4k,很多浏览器都会限制一个站点最多保存20个cookie

 

 

 

3.servlet的生命周期

 

 

4.JSP和Servlet的区别

 

 

 

 

计算机网络

 

1.http和https的区别

  • http是http协议运行在tcp之上,所有传输的内容都是明文,客户端和服务器都无法验证对方的身份
  • https是http运行在ssl/tls智商,ssl/tls运行在tcp之上,所有传输的内容都经过加密,加密采用对称加密,但对成加密的秘钥用服务器房的整数进行了肺对成加密,此外客户端可以验证服务器的身份,如果配置了客户端验证,服务方也可以验证客户端的身份
  • https协议需要用到ca申请证书,一般免费的证书很少,需要交费
  • http是超文本传输协议,信息是铭文传输,https则是具有安全性的加密传输协议
  • http和https使用完全不同的连接方式,用的端口也不一样,前者是80,后者是443

 

2.tcp如何保证可靠性传输?三次握手过程

  • tcp如何保证可靠传输
    • 数据包校验
    • 超时重传机制
    • 应答机制
    • 对失序数据包进行重排序
    • TCP还能提供流量控制
  • 三次握手以及四次挥手 

  三次握手和四次挥手详解   

 

 

3.为什么tcp连接需要三次握手,两次不可以么?

  •  为了防止已失效的连接请求突然又传送到了服务端,而产生错误
  • 例子
    • 已失效的连接请求报文的产生在这样一种情况下,client发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间的滞留了,一直延误到了连接释放以后的某个时间才到server,本来这是一个早已失效的报文段,但是server收到次失效的连接请求报文段后,误认为是client再次发出的心的连接的请求,于是就想client发出确认报文段,同意建立连接,假设不采用三次握手,那么只要server发出确认新的连接就建立了,,由于现在client并没有发出连接请求,因此不会理会server的确认,也不会向server发送数据,但server却以为新的运输连接已经建立,并一直等待client发来数据,这样server许多资源就浪费了,利用三次握手可防止以上事情发生

 

4.如果客户端不断的发送请求连接会怎么样

 

 

5.get和post的区别
  • GET被强制服务器支持
  • 浏览器对URL的长度有限制,所以GET请求不能代替POST请求发送大量数据
  • GET请求发送数据更小
  • GET请求是不安全的
  • GET请求是幂等的
  • POST请求不能被缓存
  • POST请求相对GET请求是安全的
  • 以下情况,请使用POST请求
    • 无法使用缓存文件
    • 向服务器发送大量数据(POST没有数据量限制)
    • 发送包含未知字符的用户输入,POST比GET更稳定也更可靠
    • POST比GET安全性更高

 

 

6.tcp和udp的区别
  • TCP和UDP的区别
    • udp是无连接的,即发送数据之前不需要建立连接
    • udp使用尽量最大努力教父,即不保证可靠教父,同时也不使用拥塞控制
    • udp是面向报文的,udp没有拥塞控制,很适合多媒体通信要求
    • udp支持一对一,一对多,多对一,多对多的交互通信
    • udp的首部开销少,只有8个字节
    • tcp是面向连接的运输层协议
    • 每一条tcp连接只能有两个端点,每一个tcp连接只能是点对点的
    • tcp提供可靠交付的服务
    • tcp提供全双工通信
    • tcp是面向字节流的
    • 首部最低20个字节
  •  tcp加快传输效率的方法
    • 采用一块确认的机制

 

7.滑动窗口算法

  •  

 

8.tcp的阻塞处理
  • 慢启动
  • 拥塞避免
  • 拥塞发生
  • 快速恢复

 

 

9.从输入网址到获取页面的过程

  •  查询DNS获取域名对应的IP地址
    • 浏览器自身的DNS缓存
    • 搜索操作系统的DNS缓存
    • 发起一个DNS的系统调用
      • 宽带运营服务器查看本身缓存
      • 运营商服务器发起一个迭代DNS解析请求
  • 浏览器获得域名对应的ip地址后,发起http三次握手
  • tcp/ip建立起来后,浏览器就可以向服务器发送http请求了
  • 服务器接收到这个请求,根据参数,经过后端处理生成html页面代码返回给浏览器
  • 浏览器拿到代码开始解析渲染,如果引用外部JS,CSS等,他们同样也是一个个的http请求,都要经过上面的步骤的
  • 渲染后把一个完整的页面呈现给用户     

 

10.说一下http请求(面试问过)

 

 

 

常用算法

 

1.如何判断一个单链表是否有环

 

public static boolean hasCycle(ListNode head) {

        ListNode quick = head;
        ListNode slow = head;

        //循环判断一下当前的slow是不是为空 ,quick是不是为空 quick.next是不是空
        while(slow != null && quick != null && quick.next != null ){

            slow = slow.next;
            quick = quick.next.next;

            if(slow == quick){
                return true;
            }

        }

        return false;

}

 

 

2.快速排序,过程,复杂度?什么情况下适用,不适用

 

 

3.什么是二叉平衡树,如何插入节点,删除节点

 

 

4.二分搜索的过程

 

 

5.归并排序的过程,时间复杂度,空间复杂度

 

 

6.给你一万个数,如何找出里面的所有的重复的数,用你能想到的方法,时间和空间复杂度分别是多少

 

 

7.给你一个数组,如何找到和为K的两个数

 

 

8.100000个数找出最小或最大的10个

 

 

操作系统

 

转载于:https://www.cnblogs.com/KanHin/p/10419812.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值