【7万字干货】2021Java实习必看面试两百题解析

①本身想总结一篇同时包含质与量的文章,给本身,也给关注个人人。
②最近在投递实习,因此主要都是Java的基础知识,计算机网络和操做系统就只挑重点,本文后面视状况会继续更新。之后可能会完善包括数据结构和算法、场景题、Linux之类的内容。
③全部题目及答案所有手打,转载注明出处。
④若有有错误欢迎指出。
⑤若是不喜欢直接关掉,别吐槽。css


JavaSE 88

基础语法 9

Q1:简单说说Java有哪些数据类型
答:①分为基本数据类型和引用数据类型。②基本数据类型包括:数值型(byte、short、int、long、float、double),字符型(char)以及布尔型(boolean)。除了基本类型外,其余数据类型都属于引用类型,包括类、接口、数组等。html

Q2:float number=3.4;有没有问题?为何?
答:有问题,由于3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于向下转型,可能会形成精度损失,因此必须进行强制类型转换,正确的写法是float number =(float)3.4;/ float number =3.4F;前端

Q3:字符串拼接的方式以及效率?
答:①使用+直接拼接,String 是final对象,不会被修改,每次使用 +进行拼接都会建立新的对象,而不是改变原来的对象,效率低,是线程安全的。②使用StringBuffer可变字符串,效率较高,是线程安全的(StringBuffer的方法使用了synchronized关键字进行修饰)。③使用StringBuilder可变字符串,效率最高,可是线程不安全。java

Q4:简述final,finally和finalize区别
答:①final能够修饰类,方法和变量,被final修饰的类不可继承,被final修饰的方法不可重写,被final修饰的变量引用不可更改,引用的内容能够更改。②finally用于try-catch代码块中,不管是否发生异常最后都将执行,做用是释放资源。③finalize是Object类的方法,在对象被垃圾回收以前将调用一次,通常用于资源的释放。程序员

Q5:==和equals有什么区别?equals和hashCode有什么联系?
答:①若是是引用类型,==比较的是两个对象的引用是否彻底相同,若是是基本类型,比较的是两个基本类型的数值是否相同。②若是没有重写的话,equals默认按照==进行比较,若是重写了equals()方法,则按照对应的比较规则比较。③两个对象若是相等,那么它们的hashCode值必须相等,但两个对象的hashCode值相等时,它们不必定相同。web

Q6:Array和ArrayList的区别?
答:①Array长度在定义以后就不运行改变了,而ArrayList是长度可变的,能够自动扩容。②Array只能存储相同类型的数据,ArrayList能够存储不一样类型的数据。③ArrayList提供了更多操做数据的方法。redis

Q7:&和&&的区别?
答:①&具备按位与和逻辑与两个功能。②&&做为逻辑与具备短路的特色,当前面的条件表达式为false时就不会进行后面条件表达式的判断,能够用来避免空指针异常。算法

Q8:简述JDK8的新特性
答:①接口中能够添加default修饰的非抽象方法,能够有方法体和内容。②能够使用lambda表达式,减小代码冗余。③函数式接口,使用@FunctionalInterface注解标明,该接口有且仅有一个抽象方法。④方法引用,能够直接引用已有Java类或对象的方法或构造器,进一步简化lambda表达式。⑤stream流,用于解决已有集合/数组类库的弊端,简化其操做,有foreach遍历、filter过滤、map映射、concat合并等功能。⑥增长日期相关的API。spring

Q9:Stream流了解吗?
答:①Stream流是JDK1.8的新特性,用于解决已有集合/数组类库的弊端,简化集合/数组的操做。②stream流的获取:集合:直接调用stream()方法获取;数组:使用静态方法Stream.of()/Arrays.stream()获取。③经常使用方法:forEach() 遍历;count() 统计个数;filter() 按条件过滤;limit() 取前面n个元素;skip() 跳过前面n个元素;map() 映射加工;concat() 合并stream流。④终结方法:foreach/count 调用终结方法后流不能继续使用;非终结方法:每次调用完返回一个新的stream对象,能够继续使用,支持链式编程。⑤收集stream流:把流转为Set集合 collect(Collections.toSet());把流转为List集合 collect(Collections.toList());把流转为Collection集合 collect(Collections.toCollection());把流转为数组 toArray()sql


面向对象 10

Q1:简述面向对象的特性
答:①封装:建议成员变量私有,而后提供公有的getter/setter方法来获取值/赋值,封装的核心思想是合理隐藏,合理暴露,能够提升安全性,实现代码的组件化。②继承:一种子类到父类的关系,是“is a”关系,能够提升代码的复用性,相同代码可写到父类,子类的功能更增强大,不只获得了父类的功能,还有本身的功能。③多态:同一个类型的对象执行相同的行为,在不一样的状态下表现出不一样的特征。多态能够下降类之间的耦合度,右边对象能够实现组件化切换,业务功能随之改变,便于扩展和维护。

Q2:类和对象有什么区别?
答:类是一个抽象的概念,是具备相同特征的事物的描述,是对象的模板。对象是一个个具体的存在,是类的实例。

Q3:列举Object类的方法
答:①equals(Object obj):判断其余对象是否与当前对象相等。②toString():打印当前对象的字符串表示。③wait():致使当前线程等待,等待其余线程唤醒,会释放锁。④notify()/notifyAll():随机唤醒一个/所有线程。⑤hashCode():返回当前对象的hashCode值。⑥finalize():当垃圾回收器要回收对象前调用。⑦clone():建立并返回对象的一个副本。

Q4:方法重载和方法重写的区别?
答:①方法重载是同一个类中具备不一样参数列表的同名方法(无关返回值类型),方法重写是子类中具备和父类相同参数列表的同名方法,会覆盖父类原有的方法。②重载的返回值类型和权限修饰符,异常抛出类型没有要求,重写方法的返回值类型小于等于父类被重写方法的返回值类型,修饰符权限大于等于父类被重写方法权限修饰符,抛出的异常类型小于等于父类被重写方法抛出的异常类型。

Q5:接口和抽象类有什么区别?
答:①接口中只能定义public staic final修饰的常量,抽象类中能够定义普通变量。②接口和抽象类都不能实例化,但接口没有构造器,抽象类有构造器。③接口能够多实现,抽象类只能单继承。④接口在JDK1.8以前只能定义public abstract修饰的方法,JDK1.8开始能够定义默认方法和静态方法,JDK1.9开始能够定义私有方法,抽象类中的方法没有限制。

Q6:何时应该使用接口,何时应该使用抽象类?
答:①若是知道某个类应该成为基类,那么第一选择应该是让它成为一个接口,只有在必需要有方法定义和成员变量的时候,才应该选择抽象类。②在接口和抽象类的选择上,必须遵照这样一个原则:行为模型应该老是经过接口而不是抽象类定义。经过抽象类创建行为模型会出现的问题:若是有一个抽象类Moblie,有两个继承它的类Mobile1和Moblie2,分别有本身的功能1和功能2,若是出现一个既有功能1又有功能2的新产品需求,因为Java不容许多继承就出现了问题,而若是是接口的话只须要同时实现两个接口便可。

Q7:内部类有什么做用?有哪些分类?
答:①内部类有更好的封装性,有更多的权限修饰符,封装性能够获得更多的控制。②静态内部类:由static修饰,属于类自己,只加载一次。类能够定义的成分静态内部类均可以定义,能够访问外部类的静态变量和方法,经过new 外部类.静态内部类构造器来建立对象。③成员内部类:属于外部类的每一个对象,随对象一块儿加载。不能够定义静态成员和方法,能够访问外部类的全部内容,经过new 外部类构造器.new 成员内部类构造器来建立对象。④局部内部类:定义在方法、构造器、代码块、循环中。只能定义实例成员变量和实例方法,做用范围仅在局部代码块中。⑤匿名内部类:没有名字的局部内部类,能够简化代码,匿名内部类会当即建立一个匿名内部类的对象返回,对象类型至关于当前new的类的子类类型。
在这里插入图片描述

Q8:泛型和泛型擦除是什么?
答:①泛型的本质是参数化类型,泛型提供了编译时类型的安全检测机制,该机制容许程序在编译时检测非法的类型。②在编译阶段采用泛型时加上的类型参数,会被编译器在编译时去掉,这个过程就被称为类型擦除,所以泛型主要用于编译阶段,在编译后生成的Java字节代码文件中不包含泛型中的类型信息。

Q9:泛型标记的规范了解吗?
答:①E:值Element,在集合中使用,表示在集合中存放的元素。②T:指Type,表示Java类,包括基本的类以及自定义类。③K:指Key,表示键,例如Map集合中的Key。④V:指Value,表示值,例如Map集合中的Value。⑤N:指Number,表示数值类型。⑥:表示不肯定的Java类型。

Q10:泛型限定是什么?
答:①类型通配符使用?表示全部具体的参数类型,在使用泛型的时候,若是但愿将类的继承关系加入泛型应用中就须要对泛型作限定,具体的泛型限定有对泛型上限的限定以及对泛型下限的限定。②对泛型上限的限定使用<? extends T>,它表示该通配符所表明的类型是T类的子类型或T接口的子接口。③对泛型下限的限定使用<? super T>,它表示该通配符所表明的类型是T类的父类型或T接口的父接口。


异常 2

Q1:异常有哪些分类?出现的缘由是什么?
答:①Throwable是全部错误和异常的父类,Throwable分为Error和Exception。②Error指Java程序运行错误,出现Error一般是由于系统的内部错误或资源耗尽,Error不能在运行过程当中被动态处理,若是程序运行中出现Error,系统只能记录错误的缘由和安全终止。③Exception指Java程序运行异常,即运行中发生了不指望的状况,分为RuntimeException和CheckedException。RuntimeException指在Java虚拟机正常运行期间抛出的异常,能够被捕获并处理,例如空指针异常,数组越界等。CheckedException指编译阶段强制要求捕获并处理的异常,例如IO异常,SQL异常等。

Q2:有哪些异常处理方式?
答:①抛出异常:遇到异常不进行具体处理,而是将异常抛出给调用者,由调用者根据状况处理。抛出异常有2种形式,一种是throws,做用在方法上,一种是throw,做用在方法内。②使用try/catch进行异常的捕获处理,try中发生的异常会被catch代码块捕获,根据状况进行处理,若是有finally代码块不管是否发生异常都会执行,通常用于释放资源,JDK1.7开始能够将资源定义在try代码块中自动释放减小代码。


集合 10

Q1:简述一下集合主要有哪些类和接口,各自有什么特色
答:①主要有两个接口Collection和Map,其中Collection又包括List、Set和Queue。②List是有序的,主要包括ArrayList,LinkedList和Vector,ArrayList底层经过数组实现,线程不安全,Vector是线程安全的ArrayList,但效率较低,LinkedList底层经过双向链表实现,与ArrayList相比增删快查询慢。③Set是惟一且无序的,主要包括HashSet,LinkedHashSet和TreeSet。HashSet底层其实就是HashMap,利用了key来保证元素的惟一性。LinkedHashSet能够按照key的操做顺序排序,TreeSet支持按照默认或指定的排序规则排序。④Queue是队列结构,主要有ArrayBlockingQueue基于数组的阻塞队列、LinkedBlockingQueue基于链表的阻塞队列等。⑤Map以key-value键值对的形式存储元素,主要包括HashMap、LinkedHashMap和TreeMap。HashMap底层经过数组+链表/红黑树实现,LinkedHashMap能够按照key的操做顺序对集合排序,TreeMap能够按照默认或指定的排序规则对集合排序。

Q2:HashMap是线程安全的吗?
答:①HashMap是线程不安全的,能够使用ConcurrentHashMap保证线程安全。②ConcurrentHashMap基于减少锁粒度的思想,经过使用分段锁来实现线程安全,内部细分为不少Segment数据段,默认状况下为16个,对每一个Segment的数据都单独进行加锁操做,Segment的个数为锁的并发度。ConcurrentHashMap是由Segment数组和HashEntry数组组成的,Segment继承了可重入锁,HashEntry用来存储键值对数据。③Segment的结构和HashMap相似,是数组和链表结构,每一个Segment里面都包含一个HashEntry数组,每一个HashEntry都是一个链表结构的数据要对其进行i修改必须先得到对应的Segment锁。④多线程下只要加入的数据hashCode映射的数据段不同就能够作到并行的线程安全。

Q3:List、Set、Map有什么区别?
答:①List是有序、可重复、有索引的集合,继承了Collection集合所有功能 除了Collection的三种遍历方式外,可用索引遍历。②Set是无序,不可重复的集合,Set的实现类LinkedHashSet和TreeSet是有序的,LinkedHashSet能够按照元素插入的顺序排序,也能够按照元素操做的时间排序,TreeSet能够按照默认的比较规则或者自定义的比较规则排序。③Map是无序、以key-value的键值对形式存储元素的集合,键不可重复,值无要求,重复的键对应的值会覆盖以前的值。

Q4:HashSet是如何去重的?
答:①对于基本类型的包装类,能够直接按值进行比较。②对于引用数据类型,会先比较hashCode()返回值是否相同,若是不一样则表明不是同一个对象,若是相同则继续比较equals()方法返回值是否相同,都相同说明是同一个对象。③若是但愿内容相同的对象就表明对象相同,那么除了重写equals()方法还要重写hashCode()方法,由于内容相同的对象hashCode()值不必定相同,由于只有hashCode()和equals()都相同才说明是同一个对象。

Q5:HashMap和HashSet的底层是怎么实现的?
答:①JDK1.8以前,HashMap的底层是数组加链表实现。数组中的每一个元素都是一个单链表,链表中的每一个元素都是Entry的实现类Node的一个实例,Node包括4个属性:key、value、hash值和用于指向单链表下一个元素的next。②HashMap在查找数据时,根据hash值能够快速定位到数组的具体下标,而后对链表进行遍历查找数据的时间复杂度为O(n)。JDK1.8起对HashMap进行了优化,底层改成数组+链表或红黑树,当链表中的元素超过8个以后,HashMap会将链表结构转换未红黑树以提升查询效率,时间复杂度为O(logn)。②HashSet的底层是基于HashMap实现的,HashSet中的元素只是存放在了底层HashMap的key上, 而value使用一个static final的Object对象标识。所以HashSet 的实现比较简单,相关操做基本上都是直接调用底层HashMap的相关方法来完成的。

Q6:Collection和Collections有什么区别?
答:①Collection是一个集合接口,它包括List有序集合、Set无序集合、Queue队列等。②Collections则是Collection的一个工具类,为Collection类型的对象提供了不少方便的方法,例如addAll能够直接对Collection集合批量添加元素,shuffle能够随机打乱List集合的元素顺序,sort能够对List集合进行默认或按比较器进行排序。

Q7:迭代器是什么?
答:①迭代器实现了Iterator接口,是用于遍历Collection集合元素的一个指针。②主要有三个方法:经过iterator()得到集合的迭代器;经过hasNext()判断集合当中是否还有元素,若是有返回true,没有则返回false,初始时迭代器位于第一个元素以前;经过next()获取集合的下一个元素,并向后移动一个元素的单位。

Q8:在使用foreach循环遍历集合元素时可否添加或删除元素?
答:使用foreach循环遍历元素集合时不能修改或删除元素,经过java -c查看字节码能够发现foreach循环其实是用Iterator迭代器实现的,若是进行添加或删除元素会抛出ConcurrentModificationException异常,由于添加或删除元素会改变modCount的值,modCount是集合类的一个成员变量,表明集合的修改次数,当modCount的值和预期的exceptedModCount值不一致时就会抛出ConcurrentModificationException异常。

Q9:Queue接口中的add()/offer()、remove()/poll()、element()/peek()方法有什么区别?
答:①add()和offer()都是向队列尾部插入一个元素,区别是当超出队列界限时,add方法会抛出异常,而offer()会返回false。②remove()和poll()都是从队列头部移除一个元素并返回,区别是队列为空时remove()方法会抛出异常,poll()方法则是返回null值。③element()和 peek() 都是用于查询队列头部的元素,区别时队列为空时, element() 抛出一个异常,而 peek() 返回 null。

Q10:有哪些线程安全的集合类?
答:①Vector,是线程安全的ArrayList,底层用数组实现,经过synchronized修饰方法保证线程安全。②HashTable,是线程安全的HashMap,继承自Dictionary,经过synchronized修饰方法保证线程安全,性能较差。③ConcurentHashMap,线程安全的HashMap,经过分段锁实现线程安全,性能较好。


多线程 34

Q1:建立线程有哪几种实现方式?分别有什么优缺点?
答:①继承Thread类,重写run()方法便可。优势是编码简单,缺点是不能继承其余类,功能单一。②实现Runnable接口,重写run()方法,并将该实现类做为参数传入Thread构造器。优势是能够继承其余类,避免了单继承的局限性;适合多个相同程序代码的线程共享一个资源(同一个线程任务对象可被包装成多个线程对象),实现解耦操做,代码和线程独立。缺点是实现相对复杂。③实现Callable接口,重写call()方法,并包装成FutureTask对象,再做为参数传入Thread构造器。优势是相比方式二能够获取返回值,缺点是实现复杂。④能够经过线程池建立。

Q2:线程有哪些状态?
答:①New:用new操做建立一个新线程,此时程序还未开始运行线程中的代码。②Runnable:调用start()方法后进入可运行状态。③Blocked:阻塞状态,内部锁(不是juc中的锁)获取失败时进入阻塞状态。④Waiting:等待其余线程唤醒时进入等待状态。⑤Timed Waiting:计时等待,带超时参数的方法,例如sleep(long time)。⑥Terminated:终止状态,线程正常运行完毕或被未捕获异常终止。

Q3:什么是线程安全问题,如何解决?
答:当多个线程对同一个共享变量进行操做时可能会产生的问题。解决方法:①使用内部锁synchronized,能够使用同步代码块,若是是实例方法可用this做为锁对象,若是是静态方法,能够用类.class做为锁,或者使用同步方法底层和同步代码块同样,若是是实例方法默认用this做为锁,若是是静态方法默认使用类.class。②使用java.util.concurrent包中的锁,例如ReentrantLock。

Q4:多线程不可见问题的缘由和解决方式?
答:①不可见的缘由是每一个线程有本身的工做内存,线程都是从主内存拷贝共享变量的副本值。每一个线程都是在本身的工做内存操做共享变量的。②解决方式:加锁:得到锁后线程会清空工做内存,从主内存拷贝共享变量最新的值成为副本,修改后刷新回主内存,再释放锁;使用volatile关键字:被volatile修饰的变量会通知其余线程以前读取到的值已失效,线程会加载最新值到本身的工做内存。

Q5:说一说volatile关键字的做用
答:①保证被修饰的变量对全部线程可见,在一个线程修改了变量的值后,新的值对于其余线程是能够当即获取的。②禁止指令重排序,被修饰的变量不会被缓存在寄存器中或者对其余处理器不可见的地方,所以在读取volatile修饰的变量时老是会返回最新写入的值。③不会执行加锁操做,不会致使线程阻塞,主要适用于一个变量被多个线程共享,多个线程都可对这个变量执行赋值或读取的操做。④volatile能够严格保证变量的单次读写操做的原子性,但并不能保证像i++这种操做的原子性,由于i++在本质上是读、写两次操做。

Q6:说一说synchronized关键字的做用
答:①用于为Java对象、方法、代码块提供线程安全的操做,属于排它的悲观锁,也属于可重入锁。②被synchronized修饰的方法和代码块在同一时刻只能有一个线程访问,其余线程只有等待当前线程释放锁资源后才能访问。③Java中的每一个对象都有一个monitor监视器对象,加锁就是在竞争monitor,对代码块加锁是经过在先后分别加上monitorenter和monitorexit指令实现的,对方是否加锁是经过一个标记位来判断的。

Q7:synchronized的内部都包括哪些区域?
答:synchronized内部包括6个不一样的区域,每一个区域的数据都表明锁的不一样状态。①ContentionList:锁竞争队列,全部请求锁的线程都被放在竞争队列中。②EntryList:竞争候选列表,在锁竞争队列中有资格成为候选者来竞争锁资源的线程被移动到候选列表中。③WaitSet:等待集合,调用wait方法后阻塞的线程将被放在WaitSet。④OnDeck:竞争候选者,在同一时刻最多只有一个线程在竞争锁资源,该线程的状态被称为OnDeck。⑤Owner:竞争到锁资源的线程状态。⑥!Owner:释放锁后的状态。

Q8:简述synchronized的实现原理
答:①收到新的锁请求时首先自旋,若是经过自旋也没有获取锁资源,被放入ContentionList(该作法对于已经进入队列的线程是不公平的,体现了synchronized的不公平性)。②为了防止ContentionList尾部的元素被大量线程进行CAS访问影响性能,Owner线程会在是释放锁时将ContentionList的部分线程移动到EntryList并指定某个线程(通常是最早进入的)为OnDeck线程。Owner并无将锁直接传递给OnDeck线程而是把锁竞争的权利交给他,该行为叫作竞争切换,牺牲了公平性但提升了性能。③获取到锁的OnDeck线程会变为Owner线程,未获取到的仍停留在EntryList中。④Owner线程在被wait阻塞后会进入WaitSet,直到某个时刻被唤醒再次进入EntryList。⑤ContentionList、EntryList、WaitSet中的线程均为阻塞状态。⑥当Owner线程执行完毕后会释放锁资源并变为!Owner状态。

Q9:JDK对synchronized作了哪些优化?
答:JDK1.6中引入了适应自旋、锁消除、锁粗化、轻量级锁以及偏向锁等以提升锁的效率。锁能够从偏向锁升级到轻量级锁,再升级到重量级锁,这种过程叫作锁膨胀。JDK1.6中默认开启了偏向锁和轻量级锁,能够经过-XX:UseBiasedLocking禁用偏向锁。

Q10:volatile和synchronized的区别?
答:①volatile只能修饰实例变量和类变量,而synchronized能够修饰方法以及代码块。②
volatile只能保证数据的可见性,可是不保证原子性,synchronized是一种排它机制,能够保证原子性。只有在特殊状况下才适合取代synchronized:对变量的写操做不依赖于当前值(例如i++),或者是单纯的变量赋值;该变量没有被包含在具备其余变量的不等式中,不一样的volatile变量不能互相依赖,只有在状态真正独立于程序内的其它内容时才能使用volatile。③volatile是一种轻量级的同步机制,在访问volatile修饰的变量时并不会执行加锁操做,线程不会阻塞,使用synchronized加锁会阻塞线程。

Q11:讲一讲ReentrantLock
答:①ReentrantLock是Lock接口的实现类,是一个可重入式的独占锁,经过AQS实现。②支持公平锁与非公平锁,还提供了可响应中断锁(线程在等待锁的过程当中能够根据须要取消对锁的请求,经过interrupt方法中断)、可轮询锁(经过tryLock获取锁,若是有可用锁返回true不然当即返回false)、定时锁(经过带long时间参数的tryLock方法获取锁,若是在给定时间内获取到可用锁且当前线程未被中断返回true,若是超过指定时间则返回false,若是获取锁时被终断则抛出异常并清除已终止状态)等避免死锁的方法。③经过lock和unlock方法显式地加锁和释放锁。

Q12:synchronized和ReentrantLock有哪些区别?
答:①synchronized是隐式锁,ReentrantLock是显式锁,使用时必须在finally代码块中进行释放锁的操做。②synchronized是非公平锁,ReentrantLock能够实现公平锁。③ReentrantLock可响应中断,可轮回,为处理锁提升了更多灵活性。④synchronized是一个关键字,是JVM级别,ReentrantLock是一个接口,是API级别。⑤synchronized采用悲观并发策略,ReentrantLock采用的是乐观并发策略,会先尝试以CAS方式获取锁。

Q13:Lock接口有哪些方法?
答:①lock():给对象加锁。②tryLock()/tryLock(long time,TimeUnit unit):尝试给对象加锁,成功返回true,能够无参也能够指定等待时间。③unlock():释放锁,锁只能由持有者释放不然抛出异常。④newCondition():建立条件对象,使用条件对象管理那些已经得到锁但不知足有效条件的线程,调用await()方法把线程进入等待集,调用sign()/signAll()解除阻塞。⑤lockInterruptibly():若是当前线程未被中断则获取该锁。

Q14:Java中的锁有什么做用?有哪些分类?
答:①Java中的锁主要用于保障多并发状况下数据的一致性,线程必须先获取锁才能进行操做,能够保证数据的安全。②从乐观和悲观的角度能够分为乐观锁和悲观锁。③从获取资源的公平性能够分为公平锁和非公平锁。④从是否共享资源的角度能够分为共享锁和排它锁。⑤从锁的状态角度可分为偏向锁、轻量级锁和重量级锁。同时在JVM中还设计了自旋锁以更快地使用CPU资源。

Q15:讲一讲乐观锁和悲观锁
答:①乐观锁采用乐观的思想处理数据,在每次读取数据时都认为别人不会修改该数据,因此不会上锁。但在更新时会判断在此期间别人有没有更新该数据,一般采用在写时先读出当前版本号而后加锁的方法,具体过程为:比较当前版本号与上一次的版本号,若是一致则更新,不然重复进行读、比较、写操做。Java中的乐观锁是基于CAS操做实现的,CAS是一种原子性操做,在对数据更新以前先比较当前值和传入的值是否同样,同样则更新不然直接返回失败状态。②悲观锁采用悲观的思想处理数据,每次读取数据时都认为别人会修改数据,因此每次都会上锁,其余线程将被阻塞。Java中的悲观锁基于AQS实现,该框架下的锁会先尝试以CAS乐观锁去获取锁,若是获取不到则会转为悲观锁。

Q16:讲一讲自旋锁
答:①自旋锁认为若是持有锁的线程能在很短的时间内释放锁资源,那么那些等待竞争锁的线程就不须要作内核态和用户态之间的切换进入阻塞、挂起状态,只需等待小段时间,在等待持有锁的线程释放锁后便可当即获取锁,这样就避免了用户线程在内核态的切换上致使锁时间消耗。②优势:减小CPU的上下文切换,对于占用锁时间很是短或锁竞争不激烈的代码块来讲性能很高。③缺点:在持有锁的线程长时间占用锁或竞争过于激烈时,线程会长时间自旋浪费CPU资源,有复杂锁依赖的状况不适合使用自旋锁。

Q17:讲一讲公平锁与非公平锁
答:①公平锁指在分配锁前检查是否有线程在排队等待获取该锁,优先将锁分配给排队时间最长的线程。②非公平锁指在分配锁时不考虑线程排队等待的状况,直接尝试获取锁,获取不到锁就在排到队尾等待。③由于公平锁须要在多核状况下维护一个锁线程等待队列,基于该队列进行锁的分配,所以效率比非公平锁低不少。synchronized是非公平锁,ReentrantLock默认的lock方法也是非公平锁。

Q18:讲一讲读写锁
答:①Lock接口提供的锁是普通锁,为了提升性能Java提供了读写锁,读写锁分为读锁和写锁,读锁之间不互斥,读锁与写锁,写锁之间都互斥。②若是系统要求共享数据能够同时支持不少线程并发读,但不能支持不少线程并发写,那么读锁能大大提升效率。若是系统要求共享数据在同一时刻只能有一个线程在写,且写的过程当中不能读,则须要使用写锁。③提升juc的locks包中ReadWriteLock的实现类ReentrantReadWriteLock的readLock()和writeLock()来分别获取读锁和写锁。

Q19:讲一讲共享锁与排它锁
答:①共享锁:容许多个线程同时获取该锁,并发访问共享资源,ReentrantReadWriteLock的读锁为共享锁的实现。②排它锁:也叫互斥锁 ,每次只容许有一个线程独占该锁,ReentrantLock为排它锁的实现。③排它锁是一种悲观的加锁策略,同一时刻只容许一个线程读取锁资源,限制了读操做的并发性,由于并发读线程并不会影响数据的一致性,所以共享锁采用了乐观的加锁策略,容许多个执行读操做的线程同时访问共享资源。

Q20:锁有哪些状态?
答:①无锁,偏向锁,轻量级锁和重量级锁。②重量级锁是基于操做系统互斥量实现的,会致使进程在用户态和内核态之间来回切换,开销较大,synchronized内部基于监视器实现,监视器基于底层操做系统实现,所以属于重量级锁,运行效率不高。JDK1.6后为了减小获取锁和释放锁带来的性能消耗提升性能,引入了轻量级锁和偏向锁。③轻量级锁是相对于重量级锁而言的,核心设计实在没有多线程竞争的前提下,减小重量级锁的使用来提升性能。适用于线程交替执行同步代码块的状况,若是同一时刻有多线程访问同一个锁,会致使轻量级锁膨胀成重量级锁。④偏向锁用于在某个线程获取某个锁后,消除这个线程锁重入的开销,看起来彷佛是这个线程获得了锁的偏袒。偏向锁的主要目的是在同一个线程屡次获取某个所的状况下尽可能减小轻量级锁的执行路径,由于轻量级锁须要屡次CAS操做,而偏向锁只须要切换ThreadID时执行一次CAS操做,提升效率。出现多线程竞争锁时,JVM会自动撤销偏向锁。偏向锁是进一步提升轻量级锁性能的。⑤随着锁竞争愈来愈严重,锁可能从偏向锁升级到轻量级锁再到重量级锁,但在Java中只会单向升级不会降级。

Q21:如何进行锁优化?
答:①减小锁持有的时间:只在有线程安全要求的程序上加锁来尽可能减小同步代码块对锁的持有时间。②减少锁粒度:将单个耗时较多的锁操做拆分为多个耗时较少的锁操做来增长锁的并行度,减小同一个锁上的竞争。在减小锁的竞争后,偏向锁、轻量级锁的使用率才会提升,例如ConcurrentHashMap中的分段锁。③读分离:指根据不一样的应用场景将锁的功能进行分离以应对不一样的变化,最多见的锁分离思想就是读写锁,这样既保证了线程安全又提升了性能。④锁粗化:指为了保障性能,会要求尽量将锁的操做细化以减小线程持有锁的时间,但若是锁分的太细反而会影响性能提高,这种状况下建议将关联性强的锁操做集中处理。⑤锁消除:注意代码规范,消除没必要要的锁来提升性能。

Q22:线程池是什么?为何须要线程池?
答:①在生产中为每个任务建立一个线程存在一些缺陷,若是无限制地大量建立线程会消耗不少资源,影响系统稳定性和性能,产生内存溢出等问题。②线程池是管理一组同构工做线程的资源池,线程池与工做队列密切相关,工做队列中保存了全部须要等待执行的任务。工做线程的任务很简单,从工做队列获取任务,执行任务,返回线程池并等待下一次任务。③线程池经过重用现有的线程,能够在处理多个请求时分摊线程在建立和撤销过程当中的开销,另外一个好处是当请求到达时工做线程一般已经存在,不会出现等待线程而延迟的任务的执行,提升了响应性。经过调整线程池的大小,能够建立足够多的线程保持处理器处于忙碌状态,同时还能够防止线程过多致使内存资源耗尽。

Q23:建立线程池时,ThreadPoolExecutor构造器中都有哪些参数,有什么含义?
答:①corePoolSize: 线程池核心大小,即在没有任务执行时线程池的大小,而且只有在工做队列满了的状况下才会建立超出这个数量的线程。②maximumPoolSize: 线程池最大大小,表示可同时活动的线程数量的上限。③keepAliveTime:存活时间,若是某个线程的空闲时间超过了存活时间,那么将被标记为可回收的,而且当线程池的当前大小超过基本大小时,这个线程将被终止。④unit: 存活时间的单位,可选的参数为TimeUnit枚举中的几个静态变量: NANOSECONDSMICROSECONDSMILLISECONDSSECONDS。⑤workQueue: 线程池所使用的阻塞队列。⑥thread factory:线程池使用的建立线程工厂方法,可省略,将使用默认工厂。⑦handler:所用的拒绝执行处理策略,可省略,将使用默认拒绝执行策略。

Q24:线程池的阻塞队列有哪些选择?
答:①ArrayBlockingQueue:基于数组的有界阻塞队列。②LinkedBlockingQueue:基于链表的有界阻塞队列。③PriorityBlockingQueue:支持优先级排序的无界阻塞队列。④DelayedWorkQueue:基于优先级队列的无界阻塞队列。⑤SynchronousQueue:队列内部仅容许容纳一个元素,用于控制互斥的阻塞队列。

Q25:线程池的拒绝执行策略有哪些选择?
答:①AbortPolicy(): 线程池默认的拒绝策略,抛出RejectedExecutionException异常。②CallerRunsPolicy(): 重试添加当前的任务,他会自动重复调用execute()方法。③DiscardOldestPolicy(): 抛弃旧的任务,加入新的任务。④DiscardPolicy(): 直接抛弃当前的任务。

Q26:建立线程池的方法有哪些?
答:能够经过Executors的静态工厂方法建立线程池,内部经过重载ThreadExecutorPool不一样的构造器建立线程池。①newFixedThreadPool,建立一个固定长度的线程池,每当提交一个任务就建立一个线程,直到达到线程池的最大数量,这时线程池的规模将再也不变化(若是某个线程因为发生了未预期的异常而结束,那么线程池会补充一个新的线程)。将线程池的核心大小和最大大小都设置为参数中指定的值,建立的线程不会超时,使用LinkedBlockingQueue。②newCachedThreadPool,建立一个可缓存的线程池,若是线程池的当前规模超过了处理器需求,那么将回收空闲的线程,而当需求增长时,能够添加新的线程,线程池的规模不存在任何限制。将线程池的最大大小设置为Integer.MAX_VALUE,而将核心大小设置为0,并将超时设为1分钟,使用SynchronousQueue,这种方法建立出的线程池可被无限扩展,并当需求下降时自动收缩。③newSingleThreadExecutor,一个单线程的Executor,建立单个工做者线程来执行任务,若是这个线程异常结束,会建立另外一个线程来代替。确保依照任务在队列中的顺序来串行执行。将核心线程和最大线程数都设置为1,使用LinkedBlockingQueue。④newScheduledThreadPool,建立一个固定长度的线程池,并且以延迟或定时的方式来执行任务,相似于Timer,使用DelayedWorkQueue

Q27:线程池的工做原理?
答:①线程池刚建立时,里面没有一个线程。任务队列是做为参数传进来的。即便队列里面有任务,线程池也不会立刻执行它们。②经过 execute(Runnable command)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法。③若是workerCount<corePoolSize,那么建立并启动一个线程执行新提交的任务。若是workerCount>=corePoolSize,且线程池内的阻塞队列未满,那么将这个任务放入队列。若是workerCount>=corePoolSize,且阻塞队列已满,若知足workerCount<maximumPoolSize,那么仍是要建立并启动一个线程执行新提交的任务。若阻塞队列已满,而且workerCount>=maximumPoolSize,则根据 handler所指定的策略来处理此任务,默认的处理方式直接抛出异常。也就是处理任务的优先级为: 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,若是三者都满了,使用handler处理被拒绝的任务。④当一个线程完成任务时,它会从队列中取下一个任务来执行。⑤当一个线程没有任务可执行,超过必定的时间(keepAliveTime)时,线程池会判断,若是当前运行的线程数大于corePoolSize时,那么这个线程会被停用掉,因此线程池的全部任务完成后,它最终会收缩到corePoolSize的大小。

Q28:简述ExecutorService的生命周期
答:①ExecutorService的生命周期有3种状态:运行、关闭和已终止。②ExecutorService在初始建立时处于运行状态。③shutdown方法将执行平缓的关闭过程:再也不接受新的任务,同时等待已经提交的任务执行完成——包括那些还未开始执行的任务。shutdownNow方法将执行粗暴的关闭过程:它将尝试取消全部运行中的任务,而且再也不启动队列中还没有开始执行的任务。在ExecutorService关闭后提交的任务将有“拒绝执行处理器REH”来处理,它会抛弃任务,或者使得execute方法抛出一个未检查的RejectedExecutionException。④等全部任务都完成后,ExecutorService将转入终止状态。能够调用awaitTermination来等待ExecutorService到达终止状态,或者经过调用isTerminated来轮询ExecutorService是否已终止。一般在调用awaitTermination后会理解调用shutdown,从而产生同步地关闭ExecutorService的效果。

Q29:什么是CAS?
答:①CAS指Compare And Swap,比较并交换。CAS(V,E,N)算法包括三个参数,V表示要更新的变量的值,E表示预期的值,N表示新值。在且仅在V的值和E相等时才会将V的值设置为N,若是不一样则说明已经有其余线程作了更改,当前线程就什么也不作。最后CAS返回当前V的真实值。②CAS操做采用了乐观锁的思想,有多个线程同时使用CAS操做一个共享变量时只有一个线程会成功,失败的线程不会被挂起仅会被告知失败,而且容许再次尝试,或者放弃操做。基于这样的原理虽然CAS没有使用锁,也能够及时发现其余线程的操做进行适当地并发处理。

Q30:CAS有什么问题?(什么是ABA问题?)如何解决?
答:①CAS算法地实现有一个重要前提:须要取出内存中某时刻的数据,而后在下一刻进行比较、替换,但在这个时间差内数据可能已经发生了变化,致使ABA问题。②ABA问题指线程1从内存V位置取出A,这时线程2也从内存中取出A,并将其首先修改成B,接着又修改成A,这时线程1在进行CAS操做时会发现内存中数据还是A,而后线程1操做成功。尽管从操做角度来讲线程1成功了,可是在该过程当中实际上数据已发生了变化但并未被感知到,某些应用场景下可能会出现数据不一致的问题。③乐观锁经过版本号来解决ABA问题,具体的操做是每次执行数据修改操做时都会带上一个版本号,若是预期版本号和数据版本号一致就进行操做,并将版本号加1,不然执行失败。

Q31:讲一讲wait、sleep、yield、join方法的区别
答:①wait是Object类的方法,调用wait方法的线程会进入WAITING状态,只有等待其余线程的通知或被中断后才会解除阻塞,调用wait方法会释放锁资源。②sleep是Thread类的方法,调用sleep方法会致使当前线程进入休眠状态,与wait不一样的是该方法不会释放锁资源,进入的是TIMED-WAITING状态。③yiled方法会使当前线程让出CPU时间片给优先级相同或更高的线程,回到RUNNABLE状态,与其余线程一块儿从新竞争CPU时间片。④join方法用于等待其余线程运行终止,若是当前线程调用了另外一个线程的join方法,则当前线程进入阻塞状态,当另外一个线程结束时当前线程才能从阻塞状态转为就绪态,等待获取CPU时间片。底层使用的是wait,也会释放锁。

Q32:讲一讲线程中断
答:①interrupt方法用于向线程发送一个终止信号,会影响该线程内部的中断标识位,这个线程自己不会由于调用了interrupt方法而改变状态,状态的具体变化须要等待接收到中断标识的程序的处理结果断定。②调用interrupt方法不会中断一个正在运行的线程,只会改变内部的中断标识位的值为true。③当调用sleep方法使线程处于TIMED-WAITING状态使,调用interrupt方法会抛出InterruptedException,使线程提早结束TIMED-WAITING状态。在抛出该异常前将清除中断标识位,因此在抛出异常后调用isInterrupted方法返回的值是false。④中断状态是线程固有的一个标识位,能够经过此标识位安全终止线程。好比想终止某个线程时,先调用interrupt方法而后在run方法中根据该线程isInterrupted方法的返回值安全终止线程。

Q33:什么是守护线程?
答:①守护线程是运行在后台的一种特殊线程,独立于控制终端而且周期性地执行某种任务或等待处理某些已发生的事件。守护线程不依赖于终端,可是依赖于JVM,当JVM中仅剩下守护线程时,JVM就会退出。②经过setDaemon方法定义一个守护线程,守护线程的优先级较低,将一个用户线程设置为守护线程必需要在启动守护线程以前。

Q34:start和run方法的区别?
答:①start方法用于启动线程,真正实现了多线程,调用了start方法后,会在后台建立一个新的线程来执行,不须要等待run方法执行完毕就能够继续执行其余代码。调用start方法时,该线程处于就绪状态,并无开始运行。②run方法也叫作线程体,包含了要执行的线程的逻辑代码,在调用run方法并无建立新的线程,而是直接运行run方法中的代码。


JVM 15

Q1:类的加载机制是什么?
答:类加载到内存中主要有5个阶段,分别为①加载:将Class文件读取到运行时数据区的方法区内,在堆中建立Class对象,并封装类在方法区的数据结构的过程。②验证:主要用于确保Class文件符合当前虚拟机的要求,保障虚拟机自身的安全,只有经过验证的Class文件才能被JVM加载。③准备:主要工做是在方法区中为类变量分配内存空间并设置类中变量的初始值。④解析:将常量池中的符号引用替换为直接引用。⑤初始化:主要经过执行类构造器的<client>方法为类进行初始化,该方法是在编译阶段由编译器自动收集类中静态语句块和变量的赋值操做组成的。JVM规定,只有在父类的<client>方法都执行成功后,子类的方法才能够被执行。在一个类中既没有静态变量赋值操做也没有静态语句块时,编译器不会为该类生成<client>方法。

Q2:有哪些类加载器,类加载器的加载模型是什么,有什么好处?
答:①主要有启动类加载器,负责加载JAVA_HOME/lib中的类库;扩展类加载器,负责加载JAVA_HOME/lib/ext中的类库;应用程序类加载器,也称系统类加载器,负责加载用户类路径上指定的类库;也能够自定义类加载器。②类加载器之间的层次关系叫作双亲委派模型,要求除了顶层的启动类加载器外其他的类加载器都应当有本身的父类加载器。一个类收到类加载请求后会层层找父类加载器去尝试加载,所以全部的加载请求最终都会被传送到顶层的启动类加载器,只有当父类加载器反馈本身没法完成加载时子加载器才会尝试本身去加载。③双亲委派模型的好处是保障类加载的惟一性和安全性,例如加载rt.jar包中的java.lang.Object,不管哪个类加载最终都会委托给启动类加载器,这样就保证了类加载的惟一性。若是存在包名和类名都相同的两个类,那么该类就没法被加载。

Q3:简述JVM的内存区域
答:JVM的内存区域分为线程私有区域(程序计数器、虚拟机栈、本地方法区)、线程共享区域(堆、方法区)和直接内存。①程序计数器是一块很小的内存空间,用于存储当前线程执行字节码文件的行号指示器。②虚拟机栈是描述Java方法执行过程的内存模型,帧栈中存储了局部变量表,操做数栈,动态连接,方法出口等信息。③本地方法栈,和虚拟机栈做用相似,区别是虚拟机栈为Java方法服务,本地方法栈为Native方法服务。④JVM运行过程当中建立的对象和生成的数据都存储在堆中,堆是被线程共享的内存区域,也是垃圾回收最主要的内存区域。⑤方法区用来存储常量,静态变量、类信息、即时编译器编译后的机器码、运行时常量池等数据。

Q4:哪些状况下类不会初始化?
答:①常量在编译时会存放在使用该常量的类的常量池,该过程不要调用常量所在的类,不会初始化。②子类引用父类的静态变量时,子类不会初始化,只有父类会初始化。③定义对象数组,不会触发该类的初始化。④在使用类名获取Class对象时不会触发类的初始化。⑤在使用Class.forName()加载指定的类时,能够经过initialize参数设置是否须要初始化。⑥在使用ClassLoader默认的loadClass方法加载类时不会触发该类的初始化。

Q5:哪些状况下类会初始化?
答:①建立类的实例。②访问某个类或接口的静态变量,或对该静态变量赋值。③调用类的静态方法。④初始化一个类的子类时(初始化子类,父类必须先初始化)。⑤JVM启动时被标为启动类的类。⑥使用反射进行方法调用时。

Q6:谈谈JVM的运行时内存
答:JVM的运行时内存也叫作JVM堆,从GC角度更将其分为新生代,老年代和永久代。
其中新生代默认占1/3堆空间,老年代默认占2/3堆空间,永久代占很是少的堆空间。
新生代又分为Eden区、ServivorFrom区和ServivorTo区,Eden区默认占8/10新生代空间,ServivorFrom区和ServivorTo区默认分别占1/10新生代空间。

Q7:谈谈新生代是怎么分区的
答:①JVM新建立的对象(除了大对象外)会被存放在新生代,默认占1/3堆内存空间。因为JVM会频繁建立对象,因此新生代会频繁触发MinorGC进行垃圾回收。②新生代又分为Eden区,ServivorFrom区和ServivorTo区。③Eden区:Java新建立的对象首先会被存放在Eden区,若是新建立的对象属于大对象,则直接将其分配到老年代。大对象的定义和具体的JVM版本、堆大小和垃圾回收策略有关,通常为2KB~128KB,可经过-XX:PretenureSizeThreshold设置其大小。在Eden区的内存空间不足时会触发MinorGC,对新生代进行一次垃圾回收。②ServivorTo区:保留上一次MinorGC时的幸存者。③ServivorFrom区:将上一次MinorGC时的幸存者做为这一次MinorGC的被扫描者。

Q8:谈谈新生代的垃圾回收机制
答:新生代的GC过程叫作MinorGC,采用复制算法实现,具体过程以下:
①把在Eden区和ServivorFrom区中存活的对象复制到ServivorTo区,若是某对象的年龄达到老年代的标准,则将其复制到老年代,同时把这些对象的年龄加1。若是ServivorTo区的内存空间不够,则也直接将其复制到老年代。若是对象属于大对象,则也直接复制到老年代。②清空Eden区和ServivorFrom区中的对象。③将ServivorFrom区和ServivorTo区互换,原来的ServivorTo区成为下一次GC时的ServivorFrom区。

Q9:谈谈老年代的垃圾回收机制
答:①老年代主要存放有长生命周期的对象和大对象,老年代的GC叫MajorGC。②在老年代,对象比较稳定,MajorGC不会频繁触发。在进行MajorGC前,JVM会进行一次MinorGC,事后仍然出现老年代空间不足或没法找到足够大的连续内存空间分配给新建立的大对象时,会触发MajorGC进行垃圾回收,释放JVM的内存空间。③MajorGC采用标记清除算法,该算法首先会扫描全部对象并标记存活的对象,而后回收未被标记的对象,并释放内存空间。由于要先扫描老年代的全部对象再回收,因此MajorGC的时间较长。容易产生内存碎片,在老年代没有内存空间可分配时,会出现内存溢出异常。

Q10:谈一谈永久代
答:①永久代指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。Class在类加载时被放入永久代。②永久代和老年代、新生代不一样,GC不会在程序运行期间对永久代的内存进行清理,这也致使了永久代的内存会随着加载的Class文件的增长而增长,在加载的Class文件过多时会出现内存溢出异常,好比Tomcat引用jar文件过多致使JVM内存不足而没法启动。③在JDK1.8中,永久代已经被元数据区取代。元数据区的做用和永久代相似,两者最大的区别在于:元数据区并无使用虚拟机的内存,而是直接使用操做系统的本地内存。所以元空间的大小不受JVM内存的限制,只和操做系统的内存有关。④在JDK1.8中,JVM将类的元数据放入本地内存中,将常量池和类的静态常量放入Java堆中,这样JVM可以加载多少元数据信息就再也不由JVM的最大可用内存空间决定,而由操做系统的实际可用内存空间决定。

Q11:如何肯定对象是不是垃圾?
答:①Java采用引用计数法可达性分析来肯定对象是否应该被回收。引用计数法容易产生循环引用的问题,可达性分析经过根搜索算法实现。根搜索算法以一系列GC Roots的点做为起点向下搜索,在一个对象到任何GC Roots都没有引用链相连时,说明其已经死亡。根搜索算法主要针对栈中的引用、方法区的静态引用和JNI中的引用展开分析。②引用计数法:在Java中若是要操做对象,就必须先获取该对象的引用,所以能够经过引用计数法来判断一个对象是否能够被回收。在为对象添加一个引用时,引用计数加1;在为对象删除一个引用时,引用计数减1;若是一个对象的引用计数为0,则表示此刻该对象没有被引用,能够被回收。引用计数法容易产生循环引用问题,循环引用指两个对象相互引用,致使它们的引用一直存在,而不能被回收。③可达性分析:为了解决引用计数法的循环引用问题,Java还采用了可达性分析来判断对象是否能够被回收。具体作法是首先定义一些GC Roots对象,而后以这些GC Roots对象做为起点向下搜索,若是在GC Roots和一个对象之间没有可达路径,则称该对象是不可达的。不可达对象要通过至少两次标记才能判断其是否可被回收,若是两次标记后该对象仍然不可达,则将被垃圾回收器回收。

Q12:有哪些GC算法?分别有什么特色?
答:①标记清除算法:标记出全部须要回收的对象,而后清除可回收的对象。效率较低,而且由于在清除后没有从新整理可用的内存空间,若是内存中可被回收的小对象居多,会引发内存碎片化问题。②复制算法:将可用内存分为区域1和区域2,将新生成的对象放在区域1,在区域1满后对区域1进行一次标记,将标记后仍然存活的对象复制到区域2,而后清除区域1。效率较高而且易于实现,解决了内存碎片化的问题,缺点是浪费了大量内存,同时在系统中存在长生命周期对象时会在两区域间来回复制影响系统效率。③标记清除算法:结合了标记清除算法和复制算法的优势,标记过程和标记清除算法同样,标记后将存活的对象移动到一端,清理另外一端。④分代收集算法:根据对象不一样类型把内存划分为不一样区域,把堆划分为新生代和老年代。因为新生代的对象生命周期较短,主要采用复制算法。将新生代划分为一块较大的Eden区和两块较小的Survivor区,Servivor区又分为ServivorTo和ServivorFrom区。JVM在运行过程当中主要使用Eden和SurvivorFrom区,进行垃圾回收时将这个两个区域存活的对象复制到SurvivorTo区并清除这两个区域。老年代主要存储长生命周期的大对象,所以采用标记清除或标记整理算法。

Q13:有哪些垃圾回收器?各自有什么特色?
答:①Serial:单线程,基于复制算法,JVM运行在Client时默认的新生代垃圾收集器。②ParNew:Serial的多线程实现,基于复制算法,JVM运行在Server时默认 的新生代垃圾收集器。③Paraller Scavenge:多线程,基于复制算法,以吞吐量最大化为目标,容许较长时间的STW换取吞吐量。④Serial Old:单线程,基于标记整理算法,是JVM运行在Client模式下默认的老年代垃圾回收器,可和Serial搭配使用。⑤Parall Old:多线程,基于标记整理算法,优先考虑系统的吞吐量。⑥CMS:多线程,基于标记清除算法,为老年代设计,追求最短停顿时间。主要有四个步骤:初始标记、并发标记、从新标记、并发清除。⑥G1:将堆内存分为几个大小固定的独立区域,在后台维护了一个优先列表,根据容许的收集时间回收垃圾收集价值最大的区域。相比CMS不会产生内存碎片,而且可精确控制停顿时间。分为四个阶段:初始标记、并发标记、最终标记、筛选回收。

Q14:Java中有哪些引用类型?
答:①强引用,最多见的引用类型,把一个对象指向一个引用变量时就是强引用。强引用的对象必定为可达性状态,因此不会被垃圾回收,是内存泄漏的主要缘由。②软引用,经过SoftReference实现,若是一个对象只有软引用,当内存空间不足时将被回收。③弱引用,经过WeakReference实现,若是一个对象只有弱引用,在垃圾回收过程当中必定会被回收。④虚引用,经过PhantomReference实现,虚引用和引用队列联合使用,主要用来跟踪对象的垃圾回收过程。

Q15:JVM有哪些内存回收与回收策略?
答:①对象优先在Eden区分配:大多数状况下对象在新生代Eden区分配,当Eden区没有足够空间时,虚拟机将发起一次MinorGC。②大对象直接进入老年代:大对象是指须要大量连续内存空间的Java对象,如很长的字符串及数组。虚拟机提供了一个参数-XX:PretenureSizeThreshold,大于该值的对象会直接进入老年代,防止它在新生代之间来回复制。③长期存活的对象进入老年代:虚拟机给每一个对象定义了一个年龄计数器,若对象在Eden区出生、通过第一次MinorGC后仍存活且能被Survivor容纳,将被移到Survivor区而且对象年龄设为1。每通过一次MinorGC,年龄就加1。默认在年龄增长到15时晋升到老年代,可经过-XX:MaxTenuringThreshold设置晋升老年代的年龄阈值。④动态对象年龄断定:若是在Survivor空间中相同年龄全部对象大小超过了该空间的一半,大于等于该年龄的对象就能够直接进入老年代而不用等到达到阈值。⑤空间分配担保:发生MinorGC前,先判断老年代最大可用连续空间是否大于新生代全部对象的总空间,若是成立那么MinorGC是安全的。若是不成立会查看HandlePromotionFailure是否容许担保,若是容许会冒险进行MinorGC,不然改成一次FullGC。


反射与注解 3

Q1:简述反射的基本概念,优缺点和使用场景。
答:①在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法,对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java的反射机制。② 优势是运行时动态获取类的所有信息,缺点是破坏了类的封装性,泛型的约束性。③是框架的核心灵魂,动态代理设计模式采用了反射机制,还有 Spring、Hibernate 等框架也大量使用到了反射机制。

Q2:获取Class对象有哪几种方式?能经过Class对象获取类的哪些信息?
答:①经过类名.class②经过对象.getClass()③经过Class.forName(类的全限名);④能够经过Class对象获取类的成员变量,方法或构造器。带declared的获取方法能够获取到类的一个或所有成员变量,方法,构造器,不带declared的方法只能获取到类的public修饰的成员变量、方法或构造器,包括父类public修饰的成员变量、方法或构造器。

Q3:注解是什么,元注解是什么,有什么做用?
答:①注解是一种标记,能够使类或接口附加额外的信息,是帮助编译器和JVM完成一些特定功能的。②元注解就是自定义注解的注解,包括@Target:用来约束注解的位置,值是ElementType枚举类,包括METHOD方法、VARIABLE变量、TYPE类/接口、PARAMETER方法参数、CONSTRUCTORS构造器和LOACL_VARIABLE局部变量;@Rentention:用来约束注解的生命周期,值是RetentionPolicy枚举类,包括:SOURCE源码、CLASS字节码和RUNTIME运行时;@Documented:代表这个注解应该被javadoc工具记录;@Inherited:表面某个被标注的类型是被继承的。


IO流 5

Q1:简单说说File对象表示的是什么?File类有哪些经常使用方法?
答:①File对象表示的是操做系统上的文件或目录。②获取:getAbsolutePath() 获取绝对路径;getPath() 获取文件定义时使用的路径;getName() 获取文件名,带后缀;length() 返回文件长度,单位是字节。③判断:exists() 判断File对象表示的文件或目录是否存在;isDirectory() 判断是不是目录; isFile() 判断是不是文件。④建立和删除:createNewFile() 不存在时建立新文件;delete() 删除文件,目录(非空目录不能删除);mkdir() 建立一级目录;mkdirs() 建立多级目录,推荐使用;⑤遍历:list 获取当前目录下全部一级文件名称到一个字符串数组并返回;listFiles 获取当前目录下全部一级File对象到File数组返回。

Q2:英文、数字和中文字符在文件中分别占多大的空间?
答:①英文和数字在任何编码中都占1个字节。②中文字符在GBK编码下占2个字节,在UTF-8编码下占3个字节。

Q3:简述传统IO有哪些分类?
答:①按流的方向:输出流:把内存中的数据写出到磁盘文件或网络介质中;输入流:把磁盘文件或网络介质中的数据读取到内存中。②按流的内容:字节流:流中数据的最小单位是字节;字符流:流中数据的最小单位是字符(针对文本内容)。顶层的抽象类包括InputStream、OutputStream、Reader、Writer,它们都实现了Closeable接口。③缓冲流(BufferedInputStream/BufferedOutputStream/BufferedReader/BufferedWriter):自带一个8KB大小的缓冲池,能够将字节/字符流为缓冲字节/缓冲字符流。④字符转换流(InputStreamReader/OutputStreamWriter):能够将对应的字节流转换为字符流。⑤打印流:PrintStream,方便快速打印数据,参数是什么就打印什么。

Q4:简述BIO、NIO、AIO的区别和原理
答:①BIO是同步阻塞的,数据的读写会阻塞在一个线程中,适用于链接数目比较小且固定的架构,对服务器资源要求高,JDK1.4前的惟一选择。②NIO是同步非阻塞的,经过Selector监听Channel上事件的变化,在Channel上有数据发生变化时通知该线程进行读写操做。适用于链接数目比较多且链接比较短的架构,如聊天服务器,从 JDK1.4开始支持。③AIO是异步非阻塞的,异步是指服务端线程接收到客户端管道后就交给底层处理IO通讯,本身能够作其余事情。适用于链接数目比较多且链接比较长的架构,从JDK1.7开始支持。

Q5:序列化和反序列化是什么,有什么要求?
答:①Java在JVM运行时被建立、更新和消耗,当JVM退出时,对象也会随之销毁。能够经过Java序列化实现持久化存储,保存对象及其状态信息到字节数组中。②反序列化就是再将字节数组中存储的信息转换回Java对象。③要求类必须实现序列化接口,而且序列化和反序列化必须保持序列化的ID一致。④静态变量和被transient修饰的变量不会被序列化。


JavaWeb 19

Q1:HTTP有哪些特色
答:①HTTP是基于TCP/IP协议的。②HTTP使用的默认端口号是80。③HTTP是基于请求/响应模型的,一次请求对应一次响应。④HTTP是无状态的,每次请求之间相互独立,不能交互数据。⑤HTTP1.0每一次请求响应都会创建新的链接,HTTP1.1会复用链接。

Q2:HTTP请求数据的数据格式是什么?
答:①请求行,包括了请求方式、请求url、请求协议/版本。HTTP协议有7种请求方式,经常使用的有2种。GET方式,请求参数在请求行中,在url后、 请求的url长度有限制的、不太安全;POST方式,请求参数在请求体中、请求的url长度没有限制的、相对安全。②请求头,是客户端浏览器告诉服务器的一些信息,常见的请求头例如User-Agent,告诉服务器使用的浏览器版本信息,能够在服务器端获取该头的信息,解决浏览器的兼容性问题。Referer,能够告诉服务器,当前请求从哪里来,能够防盗链或者进行统计数据。③请求空行,用于分割POST请求的请求头和请求体的。④请求体(正文),封装POST请求消息的请求参数的。

Q3:转发和重定向的区别?
答:①转发的特色: 转发地址栏路径不变、 转发只能访问当前服务器下的资源、转发是一次请求,能够使用request对象来共享数据。②重定向的特色:地址栏发生变化、重定向能够访问其余站点(服务器)的资源、重定向是两次请求,不能使用request对象来共享数据。

Q4:讲一讲Cookie
答:①Cookie是客户端会话技术,将数据保存到客户端。②建立Cookie对象,绑定数据:new Cookie(String name, String value);发送Cookie对象:response.addCookie(Cookie cookie),一次能够发送多个Cookie;获取Cookie,拿到数据:request.getCookies()。③浏览器对于单个cookie 的大小有限制(4kb) 以及对同一个域名下的总cookie数量也有限制(20个),cookie通常用于存出少许的不太敏感的数据,在不登陆的状况下,完成服务器对客户端的身份识别。

Q5:Cookie的生命周期?
答:①默认状况下,当浏览器关闭后,Cookie数据被销毁。②若是想要持久化存储,能够使用setMaxAge(int seconds)。正数:将Cookie数据写到硬盘的文件中,持久化存储,并指定cookie存活时间,时间到后,cookie文件自动失效。负数:默认值。零:删除cookie信息。

Q6:Cookie能够存储中文数据吗?
答:①在tomcat 8 以前cookie中不能直接存储中文数据,须要将中文数据转码—通常采用URL编码(%E3)。②在tomcat 8 以后,cookie支持中文数据,特殊字符仍是不支持,建议使用URL编码存储,URL解码解析。

Q7:Cookie的共享范围是什么?
答:①假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie默认状况下不能共享。经过setPath(String path)设置cookie的获取范围,默认状况下,设置为当前的虚拟目录,若是要共享,则能够将path设置为/。②不一样的tomcat服务器间cookie共享问题:经过setDomain(String path)设置一级域名,若是一级域名相同,那么多个服务器之间cookie能够共享。例如setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie能够共享。

Q8:讲一讲Session
答:①Session是服务器端会话技术,在一次会话的屡次请求间共享数据,将数据保存在服务器端的对象中。②获取HttpSession对象:request.getSession();使用HttpSession对象:Object getAttribute(String name)void setAttribute(String name, Object value)void removeAttribute(String name)。③Session的实现是依赖于Cookie的,服务器是经过cookie中的JESSIONID判断session是不是同一个的。

Q9:Session的生命周期?当客户端关闭后,服务器不关闭,两次获取session是否为同一个?客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
答:①服务器关闭、session对象调用invalidate() 时销毁,session默认失效时间 30分钟。②在默认状况下,当客户端关闭服务端不关闭时,两次获取session值不是同一个。③若是须要相同,则能够建立Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。④客户端不关闭,服务端关闭,两次获取的session值也不是同一个。可是要确保数据不丢失。tomcat自动完成如下工做。session的钝化: 在服务器正常关闭以前,将session对象序列化到硬盘上。session的活化: 在服务器启动后,将session文件转化为内存中的session对象便可。可是IDEA不支持这种操做,由于每次用IDEA重启tomcat时会自动删除catalina_base中work目录(程序动态生成的文件),这样在关闭tomcat时生成的session序列化文件也会被删除。

Q10:Session的特色,和Cookie有什么区别?
答:①Session用于存储一次会话的屡次请求的数据,存在服务器端。session能够存储任意类型,任意大小的数据。②Session存储数据在服务器端,Cookie存储数据在客户端。
Session没有存储数据的大小限制,Cookie有数据大小限制。Session存储数据是安全的,使用Cookie存储数据相对于使用Session来讲不安全。

Q11:EL是什么?
答:①EL指Expression Language 表达式语言。②EL表达式的做用是替换和简化jsp页面中java代码的编写。③EL表达式的语法是:${表达式}。④JSP默认支持EL表达式,若是要忽略EL表达式,设置JSP中page指令中的isELIgnored="true"忽略当前jsp页面中全部的el表达式,也能够经过\${表达式} 忽略当前这个EL表达式。

Q12:JSTL是什么?
答:①JSTL指JavaServer Pages Tag Library JSP标准标签库,是由Apache组织提供的开源的免费的JSP标签。②JSTL的做用是简化和替换jsp页面上的Java代码。③使用时首先须要导入JSTL相关jar包,并引入标签库: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Q13:JSP定义Java代码有哪些方式?
答:①<% 代码 %>是JSP页面中Java代码片断的容器,将页面转换为servlet类时,会将内容插入到servlet类的jspService()方法中,同时从JSP生成servlet。②<%! 代码 %>用于为JSP页面声明全局的方法和变量。在JSP文件中,必须先声明这些变量和方法而后才能使用它们。在页面转换中,声明的方法和变量成为JSP页面的servlet类中的类成员声明。语法③<%= 代码 %>用于将转换为String的Java表达式的值插入到返回给客户端的响应中。

Q14:JSP的内置对象有哪些?
答:①pageContext,真实类型是PageContext,能够在当前页面共享数据,还能够获取其余八个内置对象。②page,真实类型是Object,指当前页面(Servlet)的对象this。③request,真实类型是HttpServletRequest,封装客户端的请求。④response,真实类型是HttpServletResponse,封装服务端对客户端的响应。⑤session,真实类型是HttpSession,封装会话数据信息。⑥out,真实类型是JspWriter,字符输出流对象,能够将数据输出到页面上,和response.getWriter()相似。response.getWriter()和out的区别:在tomcat服务器真正给客户端作出响应以前,会先找response缓冲区数据,再找out缓冲区数据。response.getWriter().write()数据输出永远在out.write()以前。⑦config,真实类型是ServletConfig,是Servlet的配置对象。⑧exception,真实类型是Throwable,封装页面抛出异常的对象。⑨application,真实类型是ServletContext,封装服务器运行环境的对象。

Q15:过滤器是什么?如何使用?
答:①当访问服务器的资源时,过滤器能够将请求拦截下来,完成一些特殊的功能。②须要实现Filter接口,使用注解方式能够在类名上加上注解@WebFilter("拦截路径"),使用XML的方式能够配置web.xml中的filter和filter-mapping标签,设置过滤器类和拦截路径。

Q16:过滤器的执行流程和生命周期是什么?
答:①执行流程:执行过滤器,执行放行后的资源,回来执行过滤器放行代码下边的代码。②生命周期:init:在服务器启动后,会建立Filter对象,而后调用init方法。只执行一次,通常用于加载资源。doFilter:在每一次请求被拦截资源时执行,会执行屡次。destroy:在服务器关闭后,Filter对象被销毁,若是服务器是正常关闭,则会执行destroy方法。只执行一次。通常用于释放资源。

Q17:过滤器拦截路径都有哪些方式?
答:①具体资源路径:,例如/index.jsp ,只有访问index.jsp资源时,过滤器才会被执行。②拦截目录:例如/user/*,当访问/user下的全部资源时,过滤器都会被执行。③经过后缀名拦截:例如*.jsp, 当访问全部后缀名为jsp资源时,过滤器都会被执行。④拦截全部资源:使用/*,访问全部资源时过滤器都会执行。

Q18:AJAX是什么?
答:①Ajax 是一种在无需从新加载整个网页的状况下,可以更新部分网页的技术。②经过在后台与服务器进行少许数据交换,Ajax 能够使网页实现异步更新。这意味着能够在不从新加载整个网页的状况下,对网页的某部分进行更新。③传统的网页(不使用 Ajax)若是须要更新内容,必须重载整个网页页面,使用Ajax技术能够提高用户的体验。

Q19:JSON是什么?如何把Java对象转为JSON?如何把JSON转回Java对象?
答:①JSON指JavaScript Object Notation JavaScript对象表示法。②JSON如今多用于存储和交换文本信息的语法,进行数据的传输。③JSON的优点是想比XML来讲占用空间更小、操做数据更快,更易解析。④将Java对象转为JSON时,须要先导入jackson的相关jar包,建立Jackson核心对象 ObjectMapper,以后调用ObjectMapper的writeValue(参数,obj)进行转换,若是参数是File类型,能够将obj对象转换为JSON字符串,并保存到指定的文件中;若是参数是Writer类型,能够将obj对象转换为JSON字符串,并将json数据填充到字符输出流中;若是参数是OutputStream类型,能够将obj对象转换为JSON字符串,并将JSON数据填充到字节输出流中。⑤将JSON转会Java对象时使用readValue的方法,参数为要转回的Java对象的Class字节码对象。


JavaEE 29

Spring 7

Q1:Spring的IOC和DI是什么?
答:①IOC即控制反转,简单来讲就是把对象的控制权委托给spring框架,做用是下降代码的耦合度。②DI即依赖注入,是IOC的一种具体实现方式。假设一个Car类须要Engine的对象,那么通常须要new一个Engine,利用IOC就是只须要定义一个私有的Engine引用变量,容器会在运行时建立一个Engine的实例对象并将引用自动注入给变量。

Q2:简述Spring中bean对象的生命周期
答:①Spring对bean进行实例化。②Spring将值和bean的引用注入到其对应的属性中。③调用BeanNameAware的setBeanName方法。④调用BeanFactoryAware的setBeanFactory方法。⑤调用AppicationContxtAware的setApplicationContext方法。⑥调用BeanPostProcessor的post-ProcessBeforeInitialization方法。⑦调用InitializingBean的after-PropertiesSet方法。若是bean使用init-method声明了自定义初始化方法,该方法也会被调用。⑧调用BeanPostProcessor的post-ProcessAfterInitialization方法。⑨使用bean。⑩调用DisposableBean的destroy方法,若是bean使用destroy-method声明了自定义销毁方法,该方法也会被调用。

Q3:简述bean的做用范围
答:经过scope指定bean的做用范围,有①singleton:单例的,每次容器返回的对象是同一个。②prototype :多例的,每次返回的对象是新建立的实例。③request:仅做用于HttpRequest,每次Http请求都会建立一个新的bean。④session:仅做用于HttpSession,不一样的Session使用不一样的实例,相同的Session使用同一个实例。⑤global session :仅做用于HttpSession,全部的Session使用同一个实例。

Q4:BeanFactory和FactoryBean,ApplicationContext的区别?
答:①BeanFactory是一个Factory接口,是用来管理bean的IOC容器或对象工厂,较为古老,不支持spring的一些插件。BeanFactory使用了延迟加载,适合多例模式。②FactoryBean是一个Bean接口,是一个能够生产或者装饰对象的工厂Bean,能够经过实现该接口自定义的实例化Bean的逻辑。③ApplicationConext是BeanFactory的子接口,扩展了其功能,ApplicationContext是当即加载,适合单例模式。通常推荐使用ApplicationContext。

Q5:使用XML配置有哪些建立Bean对象的方式?
答:①经过默认无参构造器。使用bean标签,只使用id和class属性,若是没有无参构造器会报错。②使用静态工厂,经过bean标签中的class指明静态工厂,factory-method指明静态工厂方法。③使用实例工厂,经过bean标签中的factory-bean指明实例工厂,factory-method指明实例工厂方法。

Q6:依赖注入能够注入哪些数据类型?有哪些注入方式?
答:①能够注入的数据类型有基本数据类型、String、Bean、以及集合等复杂数据类型。②有三种注入方式,第一种是经过构造器注入,经过constructor-arg标签实现,缺点是即便不须要该属性也必须注入;第二种是经过Set方法注入,经过property标签实现,优势是建立对象时没有明确限制,缺点是某个成员变量必须有值,在获取对象时set方法可能尚未执行;第三种是经过注解注入,利用@Autowired自动按类型注入,若是有多个匹配则按照指定bean的id查找,查找不到会报错;@Qualifier在自动按照类型注入的基础之上,再按照 Bean 的 id 注入,给成员变量注入时必须搭配@Autowired,给方法注入时可单独使用;@Resource直接按照 Bean 的 id 注入;@Value用于注入基本数据类型和String。

Q7:有哪些配置Bean的注解,各有什么区别?
答:①@Component,把当前类对象存入spring容器中,至关于在 xml 中配置一个 bean。value属性指定 bean 的 id,若是不指定 value 属性,默认 id 是当前类的类名,首字母小写。②@Service,通常用于业务层。③@Controller:通常用于表现层。④@Repository:通常用于持久层。⑤@Controller @Service @Repository都是针对@Component的衍生注解,做用及属性都是如出一辙的,只是提供了更加明确的语义化。


Spring Aop 4

Q1:Spring Aop的基本原理是什么?
答:Aop即面向切面编程,简单地说就是将代码中重复的部分抽取出来,在须要执行的时候使用动态代理的技术,在不修改源码的基础上对方法进行加强。优势是能够减小代码的冗余,提升开发效率,维护方便。Spring会根据类是否实现了接口来判断动态代理的方式,若是实现了接口会使用JDK的动态代理,核心是InvocationHandler接口和Proxy类,若是没有实现接口会使用cglib的动态代理,cglib是在运行时动态生成某个类的子类,若是某一个类被标记为final,是不能使用cglib动态代理的。

Q2:简单解释一下AOP的相关术语
答:①Joinpoint(链接点):指那些被拦截到的点,在 spring 中这些点指的是方法,由于 spring 只支持方法类型的链接点。例如业务层实现类中的方法都是链接点。②Pointcut(切入点):指咱们要对哪些 Joinpoint 进行拦截的定义。例如业务层实现类中被加强的方法都是切入点,切入点必定是链接点,但链接点不必定是切入点。③Advice(通知/加强):指拦截到 Joinpoint 以后所要作的事情。④Introduction(引介):引介是一种特殊的通知,在不修改类代码的前提下能够在运行期为类动态地添加一些方法或 Field。⑤Weaving(织入):是指把加强应用到目标对象来建立新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。⑥Proxy(代理):一个类被 AOP 织入加强后,就产生一个结果代理类。⑦Target(目标):代理的目标对象。⑧Aspect(切面):是切入点和通知(引介)的结合。

Q3:Spring Aop有哪些相关注解?
答:@Before前置通知,@AfterThrowing异常通知,@AfterReturning后置通知,@After最终通知,@Around环绕通知。最终通知会在后置通知以前执行,为解决此问题通常使用环绕通知。

Q4:如何使用XML方式配置AOP?
答:①aop:config用于声明开始 aop 的配置。②aop:aspect用于配置切面。属性:id给切面提供一个惟一标识。ref引用配置好的通知类 bean 的 id。③aop:pointcut用于配置切入点表达式,就是指定对哪些类的哪些方法进行加强。属性:expression用于定义切入点表达式,id用于给切入点表达式提供一个惟一标识。④aop:before用于配置前置通知,在切入点方法执行以前执行;aop:after-returning用于配置后置通知,在切入点方法正常执行以后执行,它和异常通知只能有一个执行;aop:after-throwing用于配置异常通知,在切入点方法执行产生异常后执行;aop:after用于配置最终通知,不管切入点方法执行时是否有异常,它都会在其后面执行。


Spring MVC 15

Q1:SpringMVC的做用是什么?MVC的含义分别是什么?
答:①springMVC是一种基于Java实现的mvc设计模型的请求驱动类型的轻量级Web层框架,做用包括:参数绑定(获取请求参数)、调用业务层 、进行请求响应。②mvc全名是model view controller模型视图控制器,model指数据模型,JavaBean的类,用来封装数据;view指jsp,html等用来展现数据给用户的界面;controller是整个流程的控制器,用来接收用户请求以及进行数据校验等功能。

Q2:要搭建一个最基础的SpringMVC环境,你是如何配置的?
答:①在pom.xml中导入如下jar包:org.springframework下的spring-context)、spring-web、spring-webmvc、javax.servlet下的servlet-api、javax.servlet.jsp下的jsp-api以及测试用的junit包。②建立一个springmvc.xml的springconfig配置文件,开启包扫描,注册视图解析器,配置视图的前缀和后缀。③在web.xml中配置核心控制器,servlet和servlet-mapping的映射等。

Q3:SpringMVC的基础响应流程是怎样的?
答:①浏览器发送请求,被 DispatherServlet 捕获,该 Servlet 并不处理请求,而是把请求转发出去(控制器类),转发的路径是根据请求 URL,匹配@RequestMapping 中的内容②根据执行方法的返回值和视图解析器(InternalResourceViewResolver),去指定的目录下查找指定名称的视图文件,Tomcat服务器渲染页面,作出响应。

Q4:SpringMVC响应流程中会涉及到哪些组件?
答:①DispatcherServlet:前端控制器,用户请求到达前端控制器,它就至关于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在下降了组件之间的耦合性。②HandlerMapping:处理器映射器,负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不一样的映射器实现不一样的映射方式,例如:配置文件方式,实现接口方式,注解方式等。③Handler:处理器,它就是咱们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。④HandlAdapter:处理器适配器,
经过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,经过扩展适配器能够对更多类型的处理器进行执行⑤View Resolver:视图解析器,负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果经过页面展现给用户。⑥View:视图,SpringMVC 提供了不少 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最经常使用的视图就是 jsp。通常状况下须要经过页面标签或页面模版技术将模型数据经过页面展现给用户,须要由程序员根据业务需求开发具体的页面。

Q5:讲一讲@RequestMapping注解
答:①做用:创建请求url和处理方法之间的对应关系。②做用位置:类,请求url的第一级访问目录,若是不写至关于根目录,须要以/开头;方法,请求url的第二级访问目录,能够不以/开头。③属性:value/path,绑定路径,支持多个路径,通常只配置一个路径;method 指定访问方式,可配置多个容许的访问方式,默认任何方法都支持,例如POST、GET等。

Q6:SpringMVC的参数绑定支持哪些类型,分别有哪些要求?
答:①基本数据类型和String,要求请求参数的参数名必须和控制器中方法的形参名一致,例如请求参数为name,控制器方法的形参也必须为name。②能够是Java对象,要求请求属性必须和对应的Java类中的成员变量名一致,例如input标签的name属性值为id,类中也必须有id这一个成员变量。也能够是Java对象中的List或Map集合。

Q7:如何解决请求参数中文乱码问题?
答:在web.xml中配置一个过滤器,配置一个filter标签,使用org.springframework.web.filter包下的CharacterEncodingFilter类实现,将<init-param>中的<param-name>设置为encoding,对应的<param-value>设置为UTF-8便可。而后配置对应的fiter-mapping标签,fiter-name和以前的同样,<url-pattern>设置为/*,表示对全部视图都进行编码过滤。

Q8:SpringMVC支持哪些Servlet对象做为控制器方法的参数?
答:一共有9个,包括①HttpServletRequest,指客户端的请求。②HttpServletResponse,指服务器端的响应。③HttpSession,Java平台对session机制的实现规范。④Principal,此接口表示主体的抽象概念,它能够用来表示任何实体,例如,我的、公司或登陆id。⑤Locale,用于国际化操做的类。⑥InputStream,字节输入流。⑦OutputStream,字节输出流。⑧Reader,字符输入流。⑨Writer,字符输出流。

Q9:SpringMVC的经常使用注解有哪些?
答:①@RequestParam:做用是将请求参数和控制器中方法形参绑定(请求参数名和形参名再也不要求相同)。属性包括:name/value,当和请求参数名一致可省略;required指定请求参数是否必填项;defaultValue是未提供请求参数时的默认值。②@RequestBody:做用是用于获取请求体的内容,直接使用获得的是key=value形式的字符串,把获取的json数据转换成pojo对象(get方式不可用)。③@RequestBody:做用是将控制器中方法返回的对象经过适当的转换器转换为指定的格式以后进行响应,一般用来返回JSON数据或者是XML。④@PathVariable:做用是绑定url中的占位符,例如请求url中/delete/{id},{id}就是url占位符。url支持占位符是spring3.0后加入的,是springmvc支持rest风格url的一个重要标志。属性包括name/value 指定url中占位符名称;required指定是否必须提供占位符。⑤@RequestHeader:做用是获取指定请求头的值。属性:value表明请求头的名称。⑥@CookieValue:做用是用于把指定 cookie 名称的值传入控制器方法参数。属性包括value:指定 cookie 的名称。required:是否必须有此 cookie。⑦@ModelAttribute:是 SpringMVC4.3 版本之后加入的,它能够修饰方法和参数,出如今方法上表示当前方法会在控制器的方法执行以前先执行。它能够修饰没有返回值的方法,也能够修饰有具体返回值的方法。出如今参数上,获取指定的数据给参数赋值。属性value用于获取数据的 key。key 能够是 POJO 的属性名称,也能够是 map 结构的 key。

Q10:响应数据的格式有哪些?
答:①字符串,控制器中的方法返回字符串能够指定逻辑视图名,经过视图解析器解析为物理视图地址,例如返回"success"时可解析为success.jsp页面。②返回值为空,默认访问视图解析器前缀+requestmapping路径+视图解析器后缀的视图。③ModelandView,能够经过setViewName()方法设置视图名实现指定视图的跳转。

Q11:SpringMVC中如何实现转发和重定向,有什么区别?
答:①前提是控制器方法返回值类型必须是String类型。②转发到页面return"forward:+绝对地址"。转发到控制器其余方法:return的是"forward:+类上requestmapping的地址+方法上requestmapping的地址"。③重定向到页面:return的是"redirect:+绝对地址",注意不能重定向访问WEB-INF下的资源。重定向到控制器其余方法:return的是"redirect:+类上requestmapping的地址+方法上requestmapping的地址"。重定向到外部连接:return的是"redirect:+连接地址(http://www.qq.com)"。④转发和重定向的区别是转发只是一次请求,重定向是两次请求;转发地址栏不变,重定向地址栏将改变;转发只能到内部资源,重定向能够到内部或外部资源;转发能够到WEB-INF下资源,重定向不能够。

Q12:SpringMVC实现简单文件上传有哪些要求?
答:①浏览器端要求:表单提交方式为post(get有文件大小限制)。提供文件上传框对应的标签:<input type="file">。表单的entype属性必须为multipart/form-data。②服务器端要求:使用**request.getInputStream()**获取数据。springmvc底层封装了commons-fileupload文件上传工具包。

Q13:SpringMVC的异常处理流程是什么?
答:Dao层发生的异常会向上抛出到Service层、Service层的异常会向上抛出到Controller层,Controller层的异常会继续向上抛出到SpringMVC的前端控制器,由前端控制器将异常交给SpringMVC的异常处理器进行处理。若是是自定义的异常处理器,须要实现HandlerExceptionResolver接口,并使用@Component注解配置或在对应的springconfig配置文件中注册。

Q14:SpringMVC中的拦截器和拦截器链是什么,和过滤器有什么区别?
答:①Spring MVC 的拦截器用于对处理器进行预处理和后处理,用户能够本身定义一些拦截器来实现特定的功能。拦截器链就是将拦截器按必定的顺序联结成一条链,在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其以前定义的顺序被调用。②它和过滤器的区别是:过滤器是 servlet 规范中的一部分,任何 java web 工程均可以使用,拦截器是 SpringMVC 框架本身的,只有使用了 SpringMVC 框架的工程才能用;过滤器在 url-pattern 中配置了/*以后,能够对全部要访问的资源拦截,拦截器它是只会拦截访问的控制器方法,若是访问的是 jsp、html、css、image 或者 js 是不会进行拦截的;它也是 AOP 思想的具体应用,若是要想自定义拦截器, 要求必须实现HandlerInterceptor 接口。

Q15:拦截器有哪些经常使用方法,各自有什么特色?
答:①preHandle:按拦截器定义顺序调用,只要配置了都会调用。若是程序员决定该拦截器对请求进行拦截处理后还要调用其余的拦截器,或者是业务处理器去进行处理,则返回 true,若是不须要再调用其余的组件去处理请求,则返回 false。②postHandle
按拦截器定义逆序调用,在拦截器链内全部拦截器返回成功时调用。在业务处理器处理完请求后,可是 DispatcherServlet 向客户端返回响应前被调用, 在该方法中对用户请求 request 进行处理。③afterCompletion:按拦截器定义逆序调用,只有 preHandle 返回 true时才调用。在 DispatcherServlet 彻底处理完请求后被调用,能够在该方法中进行一些资源清理的操做。


Mybatis 3

Q1:延迟加载是什么?Mybatis支持吗?
答:①Mybatis支持延迟加载。实际开发过程当中不少时候咱们并不须要老是在加载某些信息时就必定要加载其关联信息,例如在加载用户信息时不是用户关联的帐户信息不是必需的,此时就能够采用延迟加载。②延迟加载就是在须要用到数据时才进行加载,不须要用到数据时就不加载数据。延迟加载也称懒加载。③好处:先从单表查询,须要时再从关联表去关联查询,大大提升数据库性能,由于查询单表要比关联查询多张表速度要快。④坏处:由于只有当须要用到数据时,才会进行数据库查询,这样在大批量数据查询时,由于查询工做也要消耗时间,因此可能形成用户等待时间变长,形成用户体验降低。

Q2:讲一讲Mybatis的缓存
答:Mybatis的缓存分为:①一级缓存:指的是Mybatis中SqlSession对象的缓存,当咱们执行完查询结果后,查询的结果会同时存入到SqlSession为咱们提供的一块区域中,该区域的结构是一个Map,当咱们再次查询一样数据时,Mybatis会先去SqlSession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,Mybatis的一级缓存也就消失了。一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。②二级缓存:二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操做同一个 Mapper 映射的 sql 语句,多个SqlSession 能够共用二级缓存,二级缓存是跨 SqlSession 的。

Q3:如何开启Mybatis的二级缓存?
答:①在springconfig配置文件中,将setting标签的cacheEnabled值设置为true(默认值为true,因此这一步可省略)。②配置相关的 Mapper 映射文件,使用<cache>标签表示当前这个 mapper 映射将使用二级缓存。③配置 statement 上面的 useCache 属性,设置 useCache=”true”表明当前这个 statement 要使用二级缓存,若是不使用二级缓存能够设置为 false。针对每次查询都须要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。④若是是使用注解的方式,能够省略第二步,只须要在dao层接口上加上注解@CacheNamespace(blocking=true)


数据库 47

MySQL 21

Q1:MySQL主要有哪些存储引擎,分别适合哪些应用场景?
答:主要有①MyISAM,是5.5版本以前的默认存储引擎,支持表级锁,不支持事务和外键,并发效率较低,读取数据快,更新数据慢。适合以读操做为主,而且对并发性要求较低的应用。②InnoDB,MySQL目前的默认存储引擎,支持行级锁、事务和外键,并发效率好。适合对事务的完整性和并发性、数据的准确性要求比较高,增删操做多的应用。③Memory,全部的数据都保存在内存中,访问速度快,一旦服务关闭数据将丢失。适合更新不太频繁的数据量小的表用来快速获得访问结果。④Archive、Federated等。

Q2:索引是什么?
答:MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据以外,数据库系统还维护者知足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就能够在这些数据结构上实现高级查找算法,这种数据结构就是索引。

Q3:索引的优缺点有哪些?
答:①优点:提升数据检索的效率,下降数据库的IO成本。经过索引列对数据进行排序,下降数据排序的成本,下降CPU的消耗。②劣势:实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,因此索引列也是要占用空间的。 虽然索引大大提升了查询效率,同时却也下降更新表的速度,如对表进行INSERT、UPDATE、DELETE。由于更新表时,MySQL 不只要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整由于更新所带来的键值变化后的索引信息。

Q4:MySQL支持哪几种索引?
答:①BTREE 索引 : 最多见的索引类型,大部分索引都支持 B 树索引。②HASH 索引:只有Memory引擎支持 , 使用场景简单 。③R-tree 索引(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,一般使用较少,不作特别介绍。④Full-text (全文索引) :全文索引也是MyISAM的一个特殊索引类型,主要用于全文索引,InnoDB从Mysql5.6版本开始支持全文索引。

Q5:B+树是什么和B树有什么区别?
答:①BTree又叫多路平衡搜索树,一颗m叉的BTree特性以下: 树中每一个节点最多包含m个孩子。 除根节点与叶子节点外,每一个节点至少有[ceil(m/2)]个孩子。若根节点不是叶子节点,则至少有两个孩子。全部的叶子节点都在同一层。每一个非叶子节点由n个key与n+1个指针组成,其中[ceil(m/2)-1] <= n <= m-1。②B+Tree为BTree的变种,B+Tree与BTree的区别为: n叉B+Tree最多含有n个key,而BTree最多含有n-1个key。 B+Tree的叶子节点保存全部的key信息,依key大小顺序排列。全部的非叶子节点均可以看做是key的索引部分。③因为B+Tree只有叶子节点保存key信息,查询任何key都要从root走到叶子。因此B+Tree的查询效率更加稳定。

Q6:MySQL的索引对B+树作了哪些优化?
答:MySql索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增长一个指向相邻叶子节点的链表指针,就造成了带有顺序指针的B+Tree,提升区间访问的性能。

Q7:索引有哪些分类?
答:①单值索引 :即一个索引只包含单个列,一个表能够有多个单列索引。②惟一索引 :索引列的值必须惟一,但容许有空值。③复合索引 :即一个索引包含多个列。

Q8:数据库的索引建立有哪些设计原则?
答:①对查询频次较高,数据量较大的表建立索引。②限制索引数量:对于增删改操做较多的表,若是索引过多将须要很高的维护代价,下降操做效率,增长操做耗时。③利用最左前缀:若是索引字段值过长,会下降索引的执行效率。④删除不经常使用索引。⑤使用惟一索引,区分度越高,效率越高。⑤使用短索引,若是索引值很长则占用磁盘变大,会影响效。⑥为常做为查询条件、常常须要排序、分组和联合操做的字段创建索引。⑦尽可能扩展示有索引,联合索引的效率高于多个独立索引。

Q9:索引在什么状况下会失效?
答:①复合索引未使用最左列索引时或跳跃使用时失效,例如以name,age和sex字段创建索引,只使用age和sex或只使用name和sex时索引失效。②在索引上进行运算或函数操做时索引失效。③数字字符没有加单引号索引失效,由于MySQL查询优化器会自动进行类型转换。④LIKE以%开头的查询索引失效,%在前时执行计划更倾向于使用全表扫描。⑤OR的先后没有同时使用索引时索引失效。⑥当全表扫描比使用索引速度更快时会使用全表扫描。

Q10:简述数据库三大范式
答:①第一范式:若是每列都是不可再分的最小数据单元,则知足第一范式。例如address:中国北京可拆分为两列,countyr:中国,city:北京。②第二范式:在第一范式的基础上,规定表中的非主键列不存在对主键的部分依赖,即第二范式要求每一个表只描述一件事情。例如订单表:订单编号、产品编号、订单日期、产品价格可拆分为订单表:订单编号、订单日期和产品表:产品编号、产品价格。③第三范式:知足第一和第二范式,而且表中的列不存在对非主键列的传递依赖。例如订单表:订单编号、订单日期、用户编号、用户姓名可优化为订单表:订单编号、订单日期、用户姓名。

Q11:MySQL数据库的隔离级别有哪些?分别有什么特色?
答:①未提交读,一个事务会读取到另外一个事务没有提交的数据,存在脏读、不可重复读、幻读的问题。②已提交读,一个事务能够读取到另外一个事务已经提交的数据,解决了幻读的问题,存在不可重复读、幻读的问题。③可重复读,MySQL默认的隔离级别,在一次事务中读取同一个数据结果是同样的,解决了不可重复读的问题,存在幻读问题。④可串行化,每次读都须要得到表级共享锁,读写互相阻塞,效率低,解决了幻读问题。

Q12:读取数据库时可能出现哪些问题?
答:①脏读,一个事务中会读取到另外一个事务中尚未提交的数据,若是另外一事务最终回滚了数据,那么所读取到的数据就是无效的。②不可重复读,一个事务中能够读取到另外一个事务中已经提交的数据,在同一次事务中对同一数据读取的结果可能不一样。③幻读,一个事务在读取数据时,当另外一个事务在表中插入了一些新数据时再次读取表时会多出几行,如同出现了幻觉。

Q13:简述事务的ACID属性
答:①Atomicity表示原子性,事务中的全部操做都是不可分割的原子单位,要么所有成功,要么所有失败。②Consistency表示一致性,不管正常执行仍是异常退出,事务执行先后数据的完整性必须保持一致,好比转帐先后双方的总金额是不变的。③Isolation表示隔离性,并发操做中不一样事务是互相隔离的,之间不会互相影响。④Durability表示持久性,事务操做完成后数据就会被持久化修改到永久存储中。

Q14:简述主从复制的基本原理
答:①主从复制是指一台服务器充当主数据库服务器,另一台或多台服务器充当从数据库服务器,主服务器中的数据自动复制到从服务器中。对于多级复制,数据库服务器既可充当主机也可充当从机。②MySQL主从复制的基础是主服务器对数据库修改二进制记录,从服务器经过主服务器的二进制日志自动执行更新。

Q15:MySQL有哪些锁?
答:①按操做类型能够分为读锁(共享锁S)和写锁(排它锁X)。读锁:对同一份数据,多个读操做能够同时进行而不会互相影响。写锁:当前操做没有完成以前,会阻塞其余读锁和写锁。②按操做粒度分为行锁、表锁、页锁。行锁指对某行数据加锁,是一种排它锁。表锁指对当前操做的整张表加锁,实现简单,资源消耗较少。③页锁的锁定粒度介于行锁和表锁之间,一次锁定相邻的一组记录。

Q16:视图是什么?和普通的表有什么区别?
答:①视图(View)是一种虚拟存在的表。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,而且是在使用视图时动态生成的。通俗的讲,视图就是一条SELECT语句执行后返回的结果集。因此咱们在建立视图的时候,主要的工做就落在建立这条SQL查询语句上。②视图相对于普通的表的优点主要包括如下几项:简单:使用视图的用户彻底不须要关心后面对应的表的结构、关联条件和筛选条件,对用户来讲已是过滤好的复合条件的结果集。安全:使用视图的用户只能访问他们被容许查询的结果集,对表的权限管理并不能限制到某个行某个列,可是经过视图就能够简单的实现。数据独立:一旦视图的结构肯定了,能够屏蔽表结构变化对用户的影响,源表增长列对视图没有影响;源表修改列名,则能够经过修改视图来解决,不会形成对访问者的影响。

Q17:存储过程和函数是什么?有什么区别?
答:①存储过程和函数是 事先通过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程和函数能够简化应用开发人员的不少工做,减小数据在数据库和应用服务器之间的传输,对于提升数据处理的效率是有好处的。 ②二者的区别在于函数必须有返回值,而存储过程没有返回值。

Q18:触发器是什么?
答:①触发器是与表有关的数据库对象,指在 insert/update/delete 以前或以后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性能够协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操做 。②使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其余的数据库是类似的。如今触发器还只支持行级触发,不支持语句级触发。

Q19:了解MySQL的体系结构吗?
答:① 链接层:最上层是一些客户端和连接服务,包含本地sock 通讯和大多数基于客户端/服务端工具实现的相似于 TCP/IP的通讯。主要完成一些相似于链接处理、受权认证、及相关的安全方案。在该层上引入了线程池的概念,为经过认证安全接入的客户端提供线程。一样在该层上能够实现基于SSL的安全连接。服务器也会为安全接入的每一个客户端验证它所具备的操做权限。②服务层:第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部份内置函数的执行。全部跨存储引擎的功能也在这一层实现,如 过程、函数等。在该层,服务器会解析查询并建立相应的内部解析树,并对其完成相应的优化如肯定表的查询的顺序,是否利用索引等, 最后生成相应的执行操做。若是是select语句,服务器还会查询内部的缓存,若是缓存空间足够大,这样在解决大量读操做的环境中可以很好的提高系统的性能。③ 引擎层:存储引擎层, 存储引擎真正的负责了MySQL中数据的存储和提取,服务器经过API和存储引擎进行通讯。不一样的存储引擎具备不一样的功能,这样咱们能够根据本身的须要,来选取合适的存储引擎。④存储层:数据存储层, 主要是将数据存储在文件系统之上,并完成与存储引擎的交互。

Q20:存储引擎应当怎样进行选择?
答:①在选择存储引擎时,应该根据应用系统的特色选择合适的存储引擎。对于复杂的应用系统,还能够根据实际状况选择多种存储引擎进行组合。如下是几种经常使用的存储引擎的使用环境。②InnoDB : 是Mysql的默认存储引擎,用于事务处理应用程序,支持外键。若是应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操做除了插入和查询意外,还包含不少的更新、删除操做,那么InnoDB存储引擎是比较合适的选择。InnoDB存储引擎除了有效的下降因为删除和更新致使的锁定, 还能够确保事务的完整提交和回滚,对于相似于计费系统或者财务系统等对数据准确性要求比较高的系统,InnoDB是最合适的选择。③MyISAM : 若是应用是以读操做和插入操做为主,只有不多的更新和删除操做,而且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是很是合适的。④MEMORY:将全部数据保存在RAM中,在须要快速定位记录和其余相似数据环境下,能够提供几块的访问。MEMORY的缺陷就是对表的大小有限制,太大的表没法缓存在内存中,其次是要确保表的数据能够恢复,数据库异常终止后表中的数据是能够恢复的。MEMORY表一般用于更新不太频繁的小表,用以快速获得访问结果。⑤MERGE:用于将一系列等同的MyISAM表以逻辑方式组合在一块儿,并做为一个对象引用他们。MERGE表的优势在于能够突破对单个MyISAM表的大小限制,而且经过将不一样的表分布在多个磁盘上,能够有效的改善MERGE表的访问效率。这对于存储诸如数据仓储等VLDB环境十分合适。

Q21:优化SQL的步骤了解吗?
答:①查看SQL执行频率。②定位低效率执行SQL。能够经过如下两种方式:慢查询日志 : 经过慢查询日志定位那些执行效率较低的 SQL 语句。show processlist : 慢查询日志在查询结束之后才记录,因此在应用反映执行效率出现问题的时候查询慢查询日志并不能定位问题,能够使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,能够实时地查看 SQL 的执行状况,同时对一些锁表操做进行优化。③经过以上步骤查询到效率低的 SQL 语句后,能够经过 EXPLAIN或者 DESC命令获取 MySQL如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程当中表如何链接和链接的顺序。④Mysql从5.0.37版本开始增长了对 show profilesshow profile 语句的支持。show profiles 可以在作SQL优化时帮助咱们了解时间都耗费到哪里了。⑤MySQL5.6提供了对SQL的跟踪trace, 经过trace文件可以进一步了解为何优化器选择A计划, 而不是选择B计划。打开trace , 设置格式为 JSON,并设置trace最大可以使用的内存大小,避免解析过程当中由于默认内存太小而不可以完整展现。


JDBC 10

Q1:了解JDBC吗?
答:①JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操做的公共接口(一组API),定义了用来访问数据库的标准Java类库(java.sql,javax.sql),使用这些类库能够以一种标准的方法方便地访问数据库资源。
②JDBC为访问不一样的数据库提供了统一的途径,为开发者屏蔽了一些细节问题。③JDBC的目标是使Java程序员使用JDBC能够链接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特色有过多的了解,从而大大简化和加快了开发过程。

Q2:JDBC的操做步骤?
答:①导入相应的jar包。②加载、注册sql驱动。③获取Connection链接对象。④建立Statement对象并执行SQL语句。⑤使用ResultSet对象获取查询结果集。⑥依次关闭ResultSet、Statement、Connection对象。

Q3:Statement和PrepatedStatement的区别是什么?
答:①Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。②PrepatedStatement:SQL 语句被预编译并存储在此对象中,能够使用此对象屡次高效地执行该语句。③使用Statement操做数据表存在弊端:存在拼串操做,繁琐;存在SQL注入问题。④PreparedStatement代码的可读性和可维护性更强,能实现更高效的批量操做。DBServer会对预编译语句提供性能优化。由于预编译语句有可能被重复调用,因此语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不须要编译,只要将参数直接传入编译过的语句执行代码中就会获得执行。在statement语句中,每执行一次都要对传入的语句编译一次。⑤PreparedStatement 能够防止 SQL 注入,还能够操做Blob类数据。

Q4:ResultSet对象存储的是什么?
答:①PreparedStatement 的 executeQuery()方法,查询结果是一个ResultSet 对象,
ResultSet 对象以逻辑表格的形式封装了执行数据库操做的结果集,ResultSet 接口由数据库厂商提供实现。②ResultSet 返回的实际上就是一张数据表,有一个指针指向数据表的第一条记录的前面。③ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行以前,能够经过 ResultSet 对象的next()方法移动到下一行。调用 next()方法检测下一行是否存在。若存在,该方法返回true,且指针下移,至关于Iterator对象的 hasNext() 和 next()方法的结合体。能够经过调用对应的getXxx()获取每一列的值。

Q5:ResultSetMetaData对象存储的是什么?
答:①可用于获取关于 ResultSet 对象中列的类型和属性信息的对象。②经过调用ResultSet对象的getMetaData()方法得到ResultSetMetaData对象,getColumnName(int column):获取指定列的名称,getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。

Q6:JDBC要释放的资源有哪些,释放的顺序是什么?
答:①释放ResultSet, Statement,Connection。②数据库链接(Connection)是很是稀有的资源,用完后必须立刻释放,若是Connection不能及时正确的关闭将致使系统问题。Connection的使用原则是尽可能晚建立,尽可能早的释放。③能够在finally中释放资源,保证及时其余代码出现异常,资源也必定能被释放。

Q7:数据库链接池是什么?它的工做原理是怎样的?
答:①传统开发模式存在的问题:普通的JDBC数据库链接使用 DriverManager 来获取,每次向数据库创建链接的时候都要将 Connection 加载到内存中,数据库的链接资源并无获得很好的重复利用。若在高并发状况下,频繁进行数据库链接操做将占用不少的系统资源,严重的甚至会形成服务器的崩溃。对于每一次数据库链接,使用完后都得断开。不然,若是程序出现异常而未能关闭,将会致使数据库系统中的内存泄漏,最终将致使重启数据库。不能控制被建立的链接对象数,系统资源会被毫无顾及的分配出去,如链接过多,也可能致使内存泄漏,服务器崩溃。②为解决传统开发中的数据库链接问题,能够采用数据库链接池技术。基本思想:就是为数据库链接创建一个“缓冲池”。预先在缓冲池中放入必定数量的链接,当须要创建数据库链接时,只需从“缓冲池”中取出一个,使用完毕以后再放回去。数据库链接池负责分配、管理和释放数据库链接,它容许应用程序重复使用一个现有的数据库链接,而不是从新创建一个。③数据库链接池在初始化时将建立必定数量的数据库链接放到链接池中,这些数据库链接的数量是由最小数据库链接数来设定的。不管这些数据库链接是否被使用,链接池都将一直保证至少拥有这么多的链接数量。链接池的最大数据库链接数量限定了这个链接池能占有的最大链接数,当应用程序向链接池请求的链接数超过最大链接数量时,这些请求将被加入到等待队列中。

Q8:数据库链接池有哪些优势?
答:①资源重用:因为数据库链接得以重用,避免了频繁建立,释放链接引发的大量性能开销。在减小系统消耗的基础上,另外一方面也增长了系统运行环境的平稳性。② 更快的系统反应速度:数据库链接池在初始化过程当中,每每已经建立了若干数据库链接置于链接池中备用。此时链接的初始化工做均已完成。对于业务请求处理而言,直接利用现有可用链接,避免了数据库链接初始化和释放过程的时间开销,从而减小了系统的响应时间。当数据库访问结束后,程序仍是像之前同样关闭数据库链接:conn.close(); 但conn.close()并无关闭数据库的物理链接,它仅仅把数据库链接释放,归还给了数据库链接池。
③ 新的资源分配手段:对于多应用共享同一数据库的系统而言,可在应用层经过数据库链接池的配置,实现某一应用最大可用数据库链接数的限制,避免某一应用独占全部的数据库资源。④ 统一的链接管理,避免数据库链接泄漏:在较为完善的数据库链接池实现中,可根据预先的占用超时设定,强制回收被占用链接,从而避免了常规数据库链接操做中可能出现的资源泄露。

Q9:数据库链接池有哪些分类?
答:①JDBC 的数据库链接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口一般由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现。②DBCP 是Apache提供的数据库链接池。tomcat 服务器自带dbcp数据库链接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已再也不提供支持。③C3P0 是一个开源组织提供的一个数据库链接池,速度相对较慢,稳定性还能够。hibernate官方推荐使用。④Druid 是阿里提供的数据库链接池,集合了DBCP 、C3P0 、Proxool 的优势。

Q10:数据源DataSource和数据库链接Connection有什么区别?
答:①DataSource 一般被称为数据源,它包含链接池和链接池管理两个部分,习惯上也常常把 DataSource 称为链接池。DataSource用来取代DriverManager来获取Connection,获取速度快,同时能够大幅度提升数据库访问速度。②数据源和数据库链接不一样,数据源无需建立多个,它是产生数据库链接的工厂,所以整个应用只须要一个数据源便可。


Redis 16

Q1:什么是NoSQL?列举几个你知道的NoSQL数据库。
答:①许多网站在海量用户访问的高并发状况下出现崩溃问题,根本缘由是关系型数据库。关系型数据库有性能瓶颈:磁盘IO性能低下、扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群。②NoSQL即Not-Only SQL,泛指非关系型数据库,做为关系型数据库的补充,下降了磁盘IO次数——使用内存存储、去除数据间关系——不存储关系,仅存储数据。③NoSQL的特征:特征:可扩容,可伸缩;大数据量下高性能;灵活的数据模型;高可用。④常见的NoSQL数据库:Redis、memcache、HBase、MongoDB。

Q2:简单讲讲Redis的含义
答:①Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。②Redis数据库中的数据间没有必然的关联关系,内部采用单线程机制进行工做,性能比较高,支持持久化存储。③支持多种数据类型,包括字符串类型 string、列表类型 list、散列类型 hash、集合类型 set、有序集合类型 sorted_set。

Q3:Redis有哪些应用场景?
答:①为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等。②应用于任务队列,如秒杀、抢购、购票排队等。③即时信息查询,如排行榜、各种网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设备信号等。④时效性信息控制,如验证码控制、投票控制等。⑤分布式数据共享,如分布式集群架构中的 session 分离以及消息队列、分布式锁等。

Q4:简述string类型的基本操做和注意事项
答:①存储的数据:单个数据,最简单经常使用的数据存储类型。存储数据的格式:一个存储空间保存一个数据。存储内容:一般使用字符串,若是字符串以整数的形式展现,能够做为数字操做使用。②添加/修改数据:set key value、获取数据:get key、删除数据:del key、添加/修改多个数据:mset key1 value1 key2 value2 ...、获取多个数据:mget key1 key2 …、获取数据字符个数(字符串长度):strlen key、追加信息到原始信息后部(若是原始信息存在就追加,不然新建):append key value。③string在redis内部存储默认就是一个字符串,当遇到增减类操做incrdecr时会转成数值型进行计算。redis全部的操做都是原子性的,采用单线程处理全部业务,命令是一个一个执行的,所以无需考虑并发 带来的数据影响。注意:按数值进行操做的数据,若是原始数据不能转成数值,或超越了redis 数值上限范围(java中long型数据最大值,Long.MAX_VALUE)将报错。

Q5:简述hash类型的基本操做和注意事项
答:①存储需求:对一系列存储的数据进行编组,方便管理,通常存储对象信息。存储结构:一个存储空间保存多个键值对数据。底层使用哈希表结构实现数据存储。②若是field数量较少,存储结构优化为类数组结构;若是field数量较多,存储结构使用HashMap结构。③添加/修改数据:hset key field value、获取数据:hget key fieldhgetall key、 删除数据:hdel key field1 [field2]、添加/修改多个数据:hmset key field1 value1 field2 value2 …、 获取多个数据:hmget key field1 field2 …、获取哈希表中字段的数量:hlen key、获取哈希表中是否存在指定的字段:hexists key field。③hash类型下的value只能存储字符串,不容许存储其余数据类型,不存在嵌套现象。若是数据未获取到, 对应的值为(nil)。每一个 hash 能够存储 2^32 - 1 个键值对。hash类型十分贴近对象的数据存储形式,而且能够灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,不可滥用,更不能够将hash做为对象列表使用。hgetall 操做能够获取所有属性,若是内部field过多,遍历总体数据效率就很会低,有可能成为数据访问瓶颈。

Q6:简述list类型的基本操做和注意事项
答:①存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分。存储结构:一个存储空间保存多个数据,且经过数据能够体现进入顺序。保存多个数据,底层使用双向链表存储结构实现。②添加/修改数据:lpush key value1 [value2] …rpush key value1 [value2] …、获取数据:lrange key start stoplindex key indexllen key、获取并移除数据:lpop keyrpop key。获取数据时能够设置等待时间,list为空时等待获取。移除指定数据:lrem key count value。③list中保存的数据都是string类型的,数据总容量是有限的,最多2^32- 1 个元素(4294967295)。list具备索引的概念,可是操做数据时一般以队列的形式进行入队出队操做,或以栈的形式进行入栈出栈操做。获取所有数据操做结束索引设置为-1。list能够对数据进行分页操做,一般第一页的信息来自于list,第2页及更多的信息经过数据库的形式加载。

Q7:简述set类型的基本操做和注意事项
答:①存储需求:存储大量的数据,在查询方面提供更高的效率。存储结构:可以保存大量的数据,高效的内部存储机制,便于查询。与hash存储结构彻底相同,仅存储键,不存储值(nil),而且值是不容许重复的。②添加数据:sadd key member1 [member2]、获取所有数据:smembers key、删除数据:srem key member1 [member2]、获取集合数据总量:scard key、判断集合中是否包含指定数据:sismember key member。③set 类型不容许数据重复,若是添加的数据在 set 中已经存在,将只保留一份。set 虽然与hash的存储结构相同,可是没法启用hash中存储值的空间。

Q8:简述sorted-set类型的相关操做和注意事项
答:①存储需求:数据排序有利于数据的有效展现,须要提供一种能够根据自身特征进行排序的方式。存储结构:新的存储模型,能够保存可排序的数据,在set的存储结构基础上添加可排序字段。②添加数据:zadd key score1 member1 [score2 member2]、获取所有数据:zrange key start stop [WITHSCORES]zrevrange key start stop [WITHSCORES]、删除数据:zrem key member [member ...]。③score保存的数据存储空间是64位,超过该范围的话score保存的数据也能够是一个双精度的double值,但可能会丢失精度,使用时候要慎重。sorted_set 底层存储仍是基于set结构的,所以数据不能重复,若是重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果。

Q9:Key有哪些通用指令?
答:①删除指定key:del key、获取key是否存在:exists key、获取key的类型:type key。②为指定key设置有效期:expire key seconds 单位秒,pexpire key milliseconds 单位毫秒、获取key的有效时间:ttl key 若是key不存在或key失效显示-2,没设置有效期或永久性显示-1,单位秒、pttl key以毫秒为单位、切换key从时效性转换为永久性:persist key。③查询key:keys pattern。查询模式规则:* 匹配任意数量的任意符号,? 配合一个任意符号,[] 匹配一个指定符号。④为key更名:rename key newkeyrenamenx key newkey新名不存在时才可以使用。

Q10:Redis如何解决key的重复问题?数据库有哪些基本操做?
答:①redis为每一个服务提供有16个数据库,编号从0到15。每一个数据库之间的数据相互独立。②切换数据库:select index、退出:quit、测试连通:ping、输出信息:echo message。③移动到其余数据库:move key db 、数据个数:dbsize 、清除该数据库:flushdb 、清除全部数据库:flushall

Q11:Jedis是什么?
答:①Jedis是一种利用Java语言链接redis的服务,须要依赖redis.clients下的jedis包。②经过new Jedis(String address,int port)建立一个操做redis数据库的对象,第一个参数是字符串类的ip地址,第二个参数是int类型的端口号。③以后经过Jedis类实例对象调用相关API实现对redis数据库的操做。

Q12:新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性?
答:redis 能够控制数据的生命周期,经过数据是否失效控制业务行为,适用于全部具备时效性限定控制的操做,使用String数据结构,经过setex key seconds value 能够设置数据有效的生命周期,有效时间以秒为单位,也能够经过psetex key milliseconds value设置数据的有效时间,有效时间以毫秒为单位。

Q13:你会如何设计与实现电商网站购物车?
答:①能够使用redis数据库,以客户id做为key,每位客户建立一个hash存储结构存储对应的购物车信息。②将商品编号做为field,购买数量做为value进行存储。③添加商品:追加全新的field与value。④浏览:遍历hash。⑤更改数量:自增/自减,设置value值。⑥删除商品:直接删除field。⑦清空购物车:直接删除key。⑧当前仅仅是将数据存储到了redis中,并无起到加速的做用,商品信息还须要二次查询数据库,将每条购物车中的商品记录保存成两条field,field1专用于保存购买数量,命名格式:商品id:nums 数值;field2专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等,命名格式:商品id:info json数据

Q14:双11活动日,销售手机充值卡的商家对移动、联通、电信的30元、50元、100元商品推出抢购活动,每种商品抢购上限1000张,你会怎么解决?
答:①使用redis的hash数据结构,以商家id做为key、将参与抢购的商品id做为field、将参与抢购的商品数量做为对应的value。②抢购时使用降值的方式控制产品数量,经过hincrby key field increment实现对指定key的field值实现值的更新操做,例如hincrby CMCC card30:nums -10实现对移动的30元商品数量实现-10操做。

Q15:微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息,若是取消点赞,移除对应好友信息,你会怎么实现?
答:redis 能够应用于具备操做前后顺序的数据控制,能够使用list数据结构实现,点赞时使用rpush key value从右添加实现顺序显示功能,取消点赞经过lrem key count value从list左边开始移除指定数据。

Q16:每位用户首次使用今日头条时会设置3项爱好的内容,可是后期为了增长用户的活跃度、兴趣点,必须让用户对其余信息类别逐渐产生兴趣,增长客户留存度,如何实现?
答:①能够利用redis数据库的set数据结构完成,系统分析出各个分类的最新或最热点信息条目并组织成set集合,随机挑选其中部分信息,配合用户关注信息分类中的热点信息组织成展现的全信息集合。②经过srandmember key [count]随机获取集合中指定数量的数据,经过spop key [count]随机获取集合中的某个数据并将该数据移出集合。


设计模式 29

Q1:设计模式是什么?
答:设计模式是通过高度抽象化的在编程中能够被反复使用的代码设计经验的总结。正确使用设计模式能提升代码的可读性、可重用性和可靠性,编写符合设计模式规范的代码不但有利于自身系统的稳定、可靠,还有利于外部系统的对接。在使用了良好设计模式的系统工程中,不管是对知足当前的需求仍是对适应将来的需求,不管是对自身系统间模块的对接仍是对外部系统的对接,都有很大帮助。

Q2:设计模式有哪些原则?
答:①单一职责原则:单一职责原则又称单一功能原则,它规定一个类只有一个职责。若是有多个职责(功能)设计在一个类中,这个类就违反了单一职责原则。②开闭原则:
开闭原则规定软件中的对象(类、模块、函数等)对扩展开放,对修改封闭,这意味着一个实体容许在不改变其源代码的前提下改变其行为,该特性在产品化的环境下是特别有价值的,在这种环境下,改变源代码须要通过代码审查,单元测试等过程以确保产品的使用质量。遵循这个原则的代码在扩展时并不发生改变,所以不须要经历上述过程。③里氏代换原则:里氏代换原则是对开闭原则的补充,规定了在任意父类能够出现的地方,子类都必定能够出现。实现开闭原则的关键就是抽象化,父类与子类的继承关系就是抽象化的具体表现,因此里氏代换原则是对实现抽象化的具体步骤的规范。④依赖倒转原则:依赖倒转原则指程序要依赖于抽象(Java中的抽象类和接口),而不依赖于具体的实现(Java中的实现类)。简单地说,就是要求对抽象进行编程,不要求对实现进行编程,这就下降了用户与实现模块之间的耦合度。⑤接口隔离原则:接口隔离原则是指经过将不一样的功能定义在不一样的接口中来实现接口的隔离,这样就避免了其余类在依赖该接口(接口上定义的功能)时依赖其不须要的接口,可减小接口之间依赖的冗余性和复杂性。
⑥合成/聚合复用原则:合成/聚合复用原则指经过在一个新的对象中引入(注入)已有的对象以达到类的功能复用和扩展的目的。它的设计原则是要尽可能使用合成或聚合而不要使用继承来扩展类的功能。⑦迪米特法则:迪米特法则指一个对象尽量少地与其余对象发生相互做用,即一个对象对其余对象应该有尽量少的了解或依赖。其核心思想在于下降模块之间的耦合度,提升模块的内聚性。迪米特法则规定每一个模块对其它模块都要有尽量少的了解和依赖,所以很容易使系统模块之间的功能独立,这使得各个模块的独立运行变得更加简单,同时使得各个模块之间的组合变得更加容易。

Q3:设计模式有哪些分类?
答:①建立型模式:提供了多种优雅建立对象的方法,包括工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。②结构型模式:经过类和接口之间的继承和引用实现建立复杂结构对象的功能,包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式。③行为型模式:经过类之间不一样的通讯方式实现不一样的行为方式,包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板模式、访问者模式。

Q4:简述工厂模式
答:①工厂模式是最多见的设计模式,该模式属于建立型模式,它提供了一种简单、快速、高效而安全地建立对象的方式。②工厂模式在接口中定义了建立对象的方法,而将具体的建立对象的过程在子类中实现,用户只需经过接口建立须要的对象便可,不用关注对象的具体建立过程。同时,不一样的子类可根据需求灵活实现建立对象的不一样方法。③通俗地讲,工厂模式的本质就是用工厂方法代替new操做建立一种实例化对象的方式,以便提供一种方便地建立有同种类型接口地产品的复杂对象。

Q5:简述抽象工厂模式
答:①抽象工厂模式在工厂模式上添加了一个建立不一样工厂的抽象接口(抽象类或接口实现),该接口可叫作超级工厂。在使用过程当中,咱们首先经过抽象接口建立出不一样的工厂对象,而后根据不一样的工厂对象建立不一样的对象。②在同一个厂商有多个维度的产品时,若是使用工厂模式,则势必会存在多个独立的工厂,这样的话设计和物理世界是不对应的。正确的作法是经过抽象工厂模式来实现,咱们能够将抽象工厂类比成厂商,将经过抽象工厂建立出来的工厂类比成不一样产品的生产线,在须要生产产品时根据抽象工厂生产。

Q6:讲一讲单例模式
答:①单例模式是保证系统实例惟一性的重要手段。单例模式首先经过将类的实例化方法私有化来防止程序经过其余方式建立该类的实例,而后经过提供一个全局惟一获取该类实例的方法帮助用户获取类的实例,用户只需也只能经过调用该方法获取类的实例。②单例模式的设计保证了一个类在整个系统中同一时刻只有一个实例存在,主要被用于一个全局类的对象在多个地方被使用而且对象的状态是全局变化的场景下。同时单例模式为系统资源的优化提供了很好的思路,频繁建立或销毁对象都会增长系统的资源消耗,而单例模式保障了整个系统只有一个对象能被使用,很好地节约了资源。③单例模式的实现很简单,每次在获取对象前都判断系统是否已经有这个单例对象,有则返回,无则建立。须要注意的是,单例模型的类构造器是私有的,只能由自身建立和销毁对象,不容许除了该类的其余程序使用new关键字建立对象及破坏单例模式。

Q7:懒汉模式线程安全吗?
答:①懒汉模式是线程不安全的,在须要时才会建立实例对象。②能够经过加synchronized锁实现线程安全的懒汉模式。③能够在加锁的基础上使用volatile关键字和双重校验锁进一步提高懒汉模式的线程安全性。

Q8:讲一讲建造者模式
答:①建造者模式使用多个简单的对象建立一个复杂的对象,用于将一个复杂的构建与其表示分离,使得一样的构建过程能够建立不一样的表示,而后经过一个Builder类(该Builder类是独立于其余对象的)建立最终的对象。②建造者模式主要用于解决软件系统中复杂对象的建立问题,好比有些复杂对象的建立须要经过各部分的子对象用必定的算法构成,在需求变化时这些复杂对象将面临很大的改变,不利于系统稳定。可是使用建造者模式能将它们各部分的算法包装起来,在需求变化后只需调整各个算法的组合方式和顺序,能极大提供系统稳定性。建造者模式常被用于一些基本部件不会变而其组合常常变化的应用场景下。③建造者模式与工厂模式的最大区别是,建造者模式更关注产品的组合方式和装配顺序,而工厂模式关注产品的生产自己。④建造者模式在设计时有如下几种角色:Builder 建立一个复杂产品对象的抽象接口、ConcreteBuilder Builder接口的实现类,用于定义复杂产品各个部件的装配流程、Director 构造一个使用Builder接口的对象、Product 表示被构造的复杂对象,ConcreteBuilder定义了该复杂对象的装配流程,而Product定义了该复杂对象的结构和内部表示。

Q9:讲一讲原型模式
答:①原型模式指经过调用原型实例的Clone方法或其余手段来建立对象。②原型模式属于建立型设计模式,它以当前对象为原型来建立另外一个新的对象,而无需知道建立的细节。原型模式在Java中一般使用Clone技术实现,在JavaScript中一般使用对象的原型属性实现。原型模式的Java实现很简单,只须要原型类实现Cloneable接口并重写clone方法便可。

Q10:浅复制和深复制的区别?
答:Java中的复制分为浅复制和深复制。①浅复制:Java中的浅复制是经过实现Cloneable接口并重写clone方法实现。在浅复制的过程当中,对象的基本数据类型的变量值会从新被复制和建立,而引用数据类型仍指向原对象的引用,也就是说浅复制不复制对象的引用数据类型。②深复制:在深复制的过程当中,不管是基本数据类型仍是引用数据类型,都会被从新复制和建立。简而言之,深复制完全复制了对象的数据,浅复制的复制不完全(忽略了引用数据类型)。

Q11:讲一讲适配器模式
答:①适配器模式经过定义一个适配器类做为两个不兼容的接口之间的桥梁,将一个类的接口转换成用户指望的另外一个接口,使得两个或多个本来不兼容的接口能够基于适配器类一块儿工做。②适配器模式主要经过适配器类实现各个接口之间的兼容,该类经过依赖注入或者继承实现各个接口的功能并对外统一提供服务。在适配器模式的实现中有三种角色:source、targetable、adapter。sourc是待适配的类,targetable是目标接口,adapter是适配器。咱们在具体应用中经过adapter将source的功能扩展到targetable,以实现接口的兼容。适配器的实现主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。

Q12:讲一讲装饰者模式
答:①装饰者模式指在无需改变原有类及类的继承关系的状况下,动态扩展一个类的功能。它经过装饰者来包裹真实的对象,并动态地向对象添加或者撤销功能。②装饰者模式包括Source和Decorator两种角色,source是被装饰者,decorator是装饰者。装饰者模式经过装饰者能够为被装饰者Source动态地添加一些功能。

Q13:讲一讲代理模式
答:①代理模式指为对象提供一种经过代理的方式来访问并控制该对象行为的方法。在客户端不适合或者不可以直接引用一个对象时,能够经过该对象的代理对象实现对该对象的访问,能够将该代理对象理解为客户端和目标对象之间的中介者。②在代理模式下有两种角色,一种是被代理者,一种是代理(Proxy),在被代理者须要作一项工做时,不用本身作而是交给代理作。以企业招聘为例,不用本身去市场找,能够经过代理去找。

Q14:讲一讲外观模式
答:①外观模式也叫作门面模式,经过一个门面向客户端提供一个访问系统的统一接口,客户端无需关心和知晓系统内部各子模块(系统)之间的复杂关系,其主要目的是下降访问拥有多个子系统的复杂系统的难度,简化客户端与其之间的接口。外观模式将子系统中的功能抽象成一个统一的接口,客户端经过这个接口访问系统,使得系统使用起来更加容易。②简单来讲外观模式就是将多个子系统及其之间的复杂关系和调用流程封装到一个统一的接口或类中以对外提供服务,这种模式设计三种角色:子系统角色:实现了子系统的功能;门面角色:外观模式的核心, 熟悉各子系统的功能和调用关系并根据客户端的需求封装统一的方法来对外提供服务;客户角色:经过调用门面来完成业务功能。

Q15:讲一讲桥接模式
答:①桥接模式经过将抽象及其实现解耦,使两者能够根据需求独立变化。这种类型的设计模式属于结构型模式,经过定义一个抽象和实现之间的桥接者来达到解耦的目的。②桥接模型主要用于解决在需求多变的状况下使用继承形成类爆炸的问题,扩展起来不够灵活。能够经过桥接模式将抽象部分与实现部分分离,使其可以独立变化而相互之间的功能不受影响。具体的作法是经过定义一个桥接接口,使得实体类的功能独立于接口实现类,下降他们之间的耦合度。

Q16:你知道哪些应用使用了桥接模式吗?
答:JDBC和DriverManager就使用了桥接模式,JDBC在链接数据库时,在各个数据库之间切换而不须要修改代码,由于JDBC提供了统一的接口,每一个数据库都提供了各自的实现,经过一个叫作数据库驱动的程序来桥接便可。

Q17:讲一讲组合模式
答:①组合模式又叫作部分总体模式,主要用于实现部分和总体操做的一致性。组合模式常根据树形结构来表示部分及总体之间的关系,使得用户对单个对象和组合对象的操做具备一致性。②组合模式经过特定的数据结构简化了部分和总体之间的关系,使得客户端能够像处理单个元素同样来处理总体的数据集,而无需关心单个元素和总体数据集之间的内部复杂结构。

Q18:讲一讲享元模式
答:①享元模式主要经过对象的复用减小对象建立的次数和数量,减小系统内存的使用和下降系统负载。享元模式属于结构型模型,在系统须要一个对象时享元模式首先在系统中查找并尝试重用现有的对象,若是未找到匹配对象则建立新对象并将其缓存在系统中。②享元模式主要用于避免在有大量对象时频繁建立和销毁对象形成系统资源的浪费,把其中共同的部分抽象出来,若是有相同的业务请求则直接返回内存中已有的对象。

Q19:讲一讲策略模式
答:①策略模式为同一个行为定义了不一样策略,为每种策略实现了不一样方法。用户使用时系统根据不一样的策略自动切换不一样的方法实现策略的改变。同一策略下的不一样方法是对同一功能的不一样实现,所以在使用时可相互替换而不影响用户的使用。②策略模式的实现是在接口中定义不一样的策略,在实现类中完成了对不一样策略下具体行为的实现,并将用户的策略状态存储在上下文中来完成策略的存储和状态的改变。

Q20:讲一讲模板方法模式
答:①模板方法模式定义了一个算法框架,并经过继承的方式将算法的实现延迟到子类中,使得子类能够在不改变算法框架及其流程的前提下从新定义该算法在某些特定环节的实现,是一种类行为型模式。②该模式在抽象类中定义了算法的结构并实现了公共部分算法,在子类中实现可变的部分并根据不一样的业务需求实现不一样的扩展。模板方法模式的优势在于其父类(抽象类)中定义了算法的框架以及保障算法的稳定性,同时在父类中实现了算法公共部分的方法保证代码的复用,将部分算法延迟到子类实现,所以子类能够经过继承扩展或从新定义算法的功能而不影响稳定性,符合开闭原则。③抽象类:定义算法框架,由基本方法和模板方法组成。基本方法定义了算法有哪些环节,模板方法定义了算法各个环节执行的流程。具体子类:对在抽象类中定义的算法根据需求进行不一样的实现。

Q21:讲一讲观察者模式
答:①观察者模式指在被观察者的状态发生变化时,系统基于事件驱动理论将其状态通知到订阅其状态的观察者对象中,以完成状态的修改和事件传播。观察者模式是一种对象行为模式,观察者和被观察者之间的关系属于抽象耦合关系,主要优势是观察者与被观察者之间创建了一套事件触发机制,以下降两者之间的耦合度。②观察者模式的主要角色以下:抽象主题Subject:持有订阅了该主题的观察者对象的集合,同时提供了增长删除观察者对象的方法和主题状态变化后的通知方法。具体主题Concrete Subject:实现了抽象主题的通知方法,在主题内部状态发生变化时,调用该方法通知订阅了主题状态的观察者对象。抽象观察者Observer:观察者的抽象类或接口,定义了主题状态变化时须要调用的方法。具体观察者 Concrete Observer:抽象观察者的实现类,在收到主题状态变化的信息后执行具体触发机制。

Q22:讲一讲迭代器模式
答:①迭代器模式提供了顺序访问集合对象中的各类元素,而不暴露该对象内部结构的方法。Java中的集合就是典型的迭代器模式,好比HashMap,当遍历HashMap时,须要迭代器不停地获取Next元素就能够循环遍历集合中全部元素。②迭代器模式将遍历集合中全部元素地操做封装成一个迭代器类,目的是在不暴露集合对象内部结构地状况下,对外提供统一访问集合内部数据的方法。迭代器的实现通常包括一个迭代器,用于执行具体的遍历操做,以及一个Collection,用于存储具体的数据。

Q23:讲一讲责任链模式
答:①责任链模式用于避免请求发送者与多个请求处理者耦合在一块儿,让全部请求的处理者持有下一个对象的引用,从而将请求串联成一条链,在有请求发生时,可将请求沿着这条链传递,直到遇到该对象的处理器。②该模式下用户只需将请求发送到责任链上便可,无需关心请求的处理细节和传递过程,因此责任链模式优雅地将请求的发送和处理进行了解耦。责任链模式经常使用于Web模式。③责任链模式包含如下三种角色:Handler接口:规定责任链上要执行的具体方法。AbstractHandler抽象类:持有Handler实例并经过get/set方法将各个具体的业务Handler串联成一个责任链,客户端上的请求在责任链上执行。业务Handler:用户根据具体的业务需求实现的业务逻辑。

Q24:讲一讲命令模式
答:①命令模式将请求封装为命令基于事件驱动异步执行,以实现命令的发送者和命令的执行者之间的解耦,提升命令发送执行的效率和灵活度。②命令模式主要包含如下角色:
抽象命令类:执行命令的接口,定义执行命令的抽象方法。具体命令类:抽象命令类的实现类,持有接收者对象,并在收到命令后调用命令执行者的方法action()实现命令的调用和执行。命令执行者:命令的具体执行者,定义了命令执行的具体方法action()。命令调用者:接收客户端的命令并异步执行。

Q25:讲一讲备忘录模式
答:①备忘录模式又叫作快照模式,该模式将当前对象的内部状态保存到备忘录中,以便在须要时能将对象的状态恢复到原先保存的状态。备忘录模式提供了一种保存和恢复状态的机制,经常使用于快照的记录和状态的存储,在系统发生鼓掌或数据发生不一致时可以方便地将数据恢复到某个历史状态。②备忘录的核心是设计备忘录类及用于管理备忘录的管理者类,主要角色以下:发起人Originator:记录当前时刻的内部状态,定义建立备忘录和回复备忘录数据的方法。备忘录Memento:负责存储对象的内部状态。状态管理者Storage:对备忘录的历史状态进行存储,定义了保存和获取备忘录状态的功能。注意备忘录只能被保存或恢复,不能进行修改。

Q26:讲一讲状态模式
答:①状态模式指给对象定义不一样的状态,并为不一样的状态定义不一样的行为,在对象的状态发生变换时自动切换状态的行为。状态模式是一种对象行为型模式,它将对象的不一样行为封装到不一样的状态中,遵循单一职责原则。②具体角色以下:环境: 也叫作上下文,用于维护对象当前的状态,并在对象状态发生变化时触发对象行为的变化。抽象状态:定义接口,用于定义对象中不一样状态对应行为。具体状态:抽象状态的实现类

Q27:讲一讲访问者模式
答:①访问者模式指将数据结构和数据的操做分离开来,使其在不改变数据结构的前提下动态添加做用于这些元素的操做。访问者模式经过定义不一样的访问者实现对数据的不一样操做,所以在须要给数据添加新的操做时只需为其定义一个新的访问者便可。②访问者模式是一种对象行为型模式,主要特色是将数据结构和做用于结构上的操做解耦,使得集合的操做可自由地演化而不影响其数据结构,它适用于数据结构稳定但操做多变的系统中。③主要角色以下:抽象访问者:定义了一个访问元素的接口,为每类元素都定义了一个访问操做,该操做中的参数类型对应被访问元素的数据类型。具体访问者:抽象访问者的实现类,实现了不一样访问者访问元素后具体行为。抽象元素:定义了访问该元素的入口方法,不一样访问者类型表明不一样访问者。具体元素:实现抽象元素定义的入口方法,根据访问者的不一样类型实现不一样逻辑业务。

Q28:讲一讲中介者模式
答:①中介者模式指对象和对象之间不直接交互,而是经过一个名为中介者的角色来实现,使原有对象之间的关系变得松散,且能够经过定义不一样的中介者来改变它们之间的交互。②主要包含如下角色:抽象中介者:中介者接口,定义了注册同事对象方法和转发同时对象信息的方法。具体中介者:中介者接口的实现类,定义了一个集合保存同事对象,协调各同事角色之间的交互关系。抽象同事类:定义同事的接口类,持有中介者对象,并定义同事对象交互的抽象方法,同时实现同事类的公共方法和功能。具体同事类:抽象同事的实现类,在须要与其余同事对象交互时,经过中介者对象来完成。

Q29:讲一讲解释器模式
答:①解释器模式给定一种语言,并定义该语言的语法表示,而后设计一个解释器来解释语言的语法,这种模式常被用于SQL解析、符号处理引擎等。②解释器模式包含如下主要角色:抽象表达式:定义解释器的接口,约定解释器所包含的操做。终结符表达式:抽象表达式的子类,用来定义语法中和终结符有关的操做,语法中的每个终结符都应有一个与之对应的终结表达式。非终结符表达式:抽象表达式的子类,用来定义语法中和非终结符有关的操做,语法中的每条规则都有一个非终结符表达式与之对应。环境:定义各个解释器须要的共享数据或公共功能。


计算机网络 7

Q1:说一说OSI网络模型
答:网络的七层架构从下到上主要包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。①物理层:物理层主要定义物理设备标准,主要做用是传输比特流,具体作法是在发送端将一、0转化为电流强弱来进行传输,在到达目的地以后再将电流强弱转化为一、0,也就是咱们常说的模数转换与数模转换,这一层的数据叫作比特。②数据链路层:数据链路层主要用于对数据包中的MAC地址进行解析和封装。这一层的数据叫作帧,在这一层工做的设备是网卡、网桥、交换机。③网络层:网络层主要用于对数据包中的IP地址进行封装和解析,这一层的数据叫作数据包。在这一层工做的设备有路由器、交换机、防火墙等。④传输层:传输层定义了传输数据的协议和端口号,主要用于数据的分段、传输和重组。在这一层工做的协议有TCP和UDP等。TCP是传输控制协议,传输效率低,可靠性强,用于传输对可靠性要求高,数据量大的数据,好比支付宝转帐业务;UDP是用户数据报协议,用于传输可靠性要求不高,数据量小的数据,例如抖音等视频服务。⑤会话层:会话层在传输层的基础上创建链接和管理会话,具体包括登录验证、断点续传、数据粘包与分包等。在设备之间须要互相识别的能够是IP,也能够是MAC或者主机名。⑥表示层:表示层主要对接收的数据进行解释、加密、解密、压缩、解压缩等,即把计算机可以识别的内容转换成人可以识别的内容(图片、声音、文字等)。⑦应用层:基于网络构建具体应用,例如FTP上传文件下载服务、Telnet服务、HTTP服务、DNS服务、SNMP邮件服务等。

Q2:说一说TCP/IP的网络模型
答:TCP/IP不是指TCP和IP这两个协议的合称,而是指因特网的整个TCP/IP协议簇。从协议分层模型方面来说,TCP/IP由4个层次组成:网络接口层、网络层、传输层和应用层。①网络接口层:定义了主机间网络连通的协议,具体包括Echernet、FDDI、ATM等通讯协议。②网络层:主要用于数据的传输、路由及地址的解析,以保障主机能够把数据发送给任何网络上的目标。数据通过网络传输,发送的顺序和到达的顺序可能发生变化。在网络层使用IP协议和ARP地址解析协议。③传输层:使源端和目的端的机器上的对等实体能够基于会话相互通讯。在这一层定义了两个端到端的协议TCP和UDP。TCP是面向链接的协议,提供可靠的报文传输和对上层应用的链接服务,除了基本的数据传输,它还有可靠性保证、流量控制、多路复用、优先权和安全性控制等功能。UDP是面向无链接的不可靠传输的协议,主要用于不须要TCP的排序和流量控制等功能的应用程序。④应用层:负责具体应用层协议的定义,包括Telnet虚拟终端协议、FTP文件传输协议、SMTP简单电子邮件传输协议、DNS域名解析服务、NNTP网上新闻传输协议和HTTP超文本传输协议等。

Q3:简述TCP的三次握手过程,为何不是两次或四次?
答:①服务端建立传输控制块TCB,进入LISTEN状态,准备接收客户端的请求。客户端一样先建立TCB,而后当准备创建链接时向服务端发送链接请求报文(SYN=1,seq=x),而后进入SYN-SENT状态。②服务端收到后向客户端发送确认报文(SYN=1,ACK=1,ack=x+1,seq=y),进入SYN-RCVD状态。③客户端接收到确认后,再向服务端发送一个确认报文(ACK=1,ack=y+1,seq=x+1),而后进入ESTABLISHED状态,服务端接收后也进入ESTABLISHED状态。
④不是两次的缘由是为了不无效的链接请求忽然发送到服务端,而此时客户端已关闭,服务端误觉得客户端将要发送数据会白白浪费资源。⑤不是四次的缘由是将服务端的SYN和ACK报文拆分红两次发送和一次的效果是相同的,没有意义。

Q4:简述TCP的四次握手过程,为何不是三次?
答:①当客户端准备关闭链接时,向服务端发送链接终止报文(FIN=1,seq=u),进入FIN-WAIT-1状态。②服务端接收后向客户端发送确认报文(ACK=1,ack=u+1,seq=v),进入CLOSE-WAIT状态,客户端收到后进入FIN-WAIT-2状态,此时TCP链接处于半关闭状态。③当服务端也发送彻底部数据准备断开链接时,向客户发送链接终止报文(FIN=1,ACK=1,ack=u+1,seq=w),进入LAST-ACK状态。④客户端接收到该报文后,发送一个确认报文(ACK=w+1,ack=1,seq=u+1),进入TIME-WAIT状态,而后等待2MSL时间后关闭。服务端收到后关闭,时间将略早于客户端。⑤不是三次的缘由第一是为了保证客户端发送的最后一个报文能够到达服务端,若是该报文丢失那么服务端会超时重传以前的FIN+ACK报文,客户端能够在2MSL内收到,第二是防止已失效的报文发送到客户端,在2MSL后客户端在本链接时间内发出的全部报文都将从网络中消失。

Q5:简述HTTP的传输流程
答:①地址解析:地址解析经过域名系统DNS解析服务器域名从而得到主机的IP地址。例如客户端的浏览器请求http://localhost:8080/index.html,则可分析出:协议名HTTP、主机名localhost、端口8080、对象路径/index.html。②封装HTTP数据包:解析协议名、主机名、端口、对象路径等并结合本机本身的信息封装成一个HTTP请求数据包。③封装TCP包:将HTTP请求数据包进一步封装成TCP数据包。④创建TCP链接:基于TCP的三次握手机制创建TCP链接。⑤客户端发送请求:在创建链接后,客户端发送一个请求给服务器。⑥服务器响应:服务器在接收到请求后,结合业务逻辑进行数据处理,而后向客户端返回相应的响应信息。在响应信息中包含状态行、协议版本号、成功或错误的代码、消息体等内容。⑦服务器关闭TCP链接:服务器在向浏览器发送请求响应数据后关闭TCP链接。但若是浏览器或者服务器在消息头加入了Connection:keep-alive,则TCP链接在请求响应数据后仍然保持链接状态,在下一次请求中浏览器能够继续使用相同的链接发送请求。采用keep-alive不但减小了请求响应的时间,还节约了网络带宽和系统资源。

Q6:HTTPS是什么?
答:HTTPS是以安全为目标的HTTP通道,它在HTTP中加入SSL层以提升数据传输的安全性。HTTP被用于在Web浏览器和网站服务器之间传递信息,但以明文方式发送内容,不提供任何方式的数据加密,若是攻击者截取了Web浏览器和网站服务器之间的传输报文,就能够直接读懂其中的信息,所以HTTP不适合传输一些敏感信息,好比身份证号码、密码等。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并对浏览器和服务器之间的通讯进行数据加密,以保障数据传输的安全性,其端口通常是443

Q7:简述HTTPS的加密流程
答:①发起请求:客户端在经过TCP和服务器创建链接以后(443端口),发出一个请求证书的消息给服务器,在该请求消息里包含本身可实现的算法列表和其余须要的消息。②证书返回:服务端在收到消息后回应客户端并返回证书,在证书中包含服务器信息、域名、申请证书的公司、公钥、数据加密算法等。③证书验证:客户端在收到证书后,判断证书签发机构是否正确,并使用该签发机构的公钥确认签名是否有效,客户端还会确认在证书中列出的域名就是它正在链接的域名。若是客户端确认证书有效,则生成对称密钥,并使用公钥将对称密钥加密。④密钥交换:客户端将加密后的对称密钥发送给服务器,服务器在接收到对称密钥后使用私钥解密。⑤数据传输:通过上述步骤,客户端和服务器就完成了密钥对的交换,在以后的数据传输过程当中,客户端和服务端就能够基于对称加密(加密和解密使用相同密钥的加密算法)对数据加密后在网络上传输,保证了网络数据传输的安全性。


操做系统 2

Q1:进程和线程有什么区别?
答:①进程是一个具备独立功能的程序关于某个数据集合的一次运行活动,是系统进行资源分配和调度的一个独立单位。②线程是一种轻量级的进程,是一个基本的CPU执行单元也是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分配的基本单位,线程不拥有系统资源,只拥有一点运行必备的资源,但可与其余同属一个进程的线程共享进程拥有的所有资源。③引入进程的目的是为了更好地使多道程序并发执行,提升系统资源利用率和吞吐量,增长并发程度。引入线程地目的使为了减少程序在并发执行时的开销,提升系统的并发能力。④堆是线程共享的,栈是线程私有的。

Q2:死锁产生的缘由和解决方法?
答:①死锁是多个进程竞争共享资源而形成互相等待的僵局,若无外力做用这些进程都将没法向前推动。②死锁产生的缘由是非剥夺资源的竞争和进程的不恰当推动顺序。③预防死锁:破坏互斥条件、破坏不剥夺条件、破坏请求和保持条件、破坏循环等待条件。④预防死锁:安全状态:能找到一个分配资源的序列让全部进程都顺序完成。银行家算法:采用预分配策略检查分配完成时系统是否处于安全状态。⑤检测死锁:利用死锁定理化简资源分配图检测死锁的存在。⑥解除死锁:资源剥夺法:挂起某些死锁进程并抢夺它的资源,以便其余线程继续推动。撤销进程法:强制撤销部分、甚至所有进程并抢夺其资源,以便让其余进程继续推动。进程回退法:让一个或多个进程回退到足以免死锁的地步。