JAVA面试208道实用题,答案持续更新整理。

一、JAVA基础

1. JDK JRE 有什么区别?

JRE(java Runtime Environment)是java运行时环境,包含了java虚拟机,java基础类库,是java语言编写的程序运行时所需要的软件环境,是提供给想运行java程序的用户使用的。

JDK(java Development kit)时java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具,还包含了java程序编写所需要的文档和demo例子程序。

2. == equals 的区别是什么?

==比较 的是变量(栈区)内存中存放的对象的(堆区)内存地址,用来判断两个对象地址是否相同,即是否指向相同一个对象。比较的是真正意义上的指针操作。

  比较的是操作符两端的操作数是否是同一个对象;

equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.object类,所以适用与所有对象,如果没有对该方法进行覆盖,Object中的equals方法等同==

public boolean equals(Object obj) {

    return (this == obj);

}

"=="比"equals"运行速度快,因为"=="只是比较引用。

3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

不一定相同,equals成立的时候hascode不一定相同,除非重写equalss和hashcode方法

两个对象==,其哈希码一定相等;

String类已经重写equals、hashCode方法,所以两个String对象equals相等时,它们的哈希码是一定相等的;

4. final Java 中有什么作用

final可以修饰类、函数、变量,即通常用来修饰你不希望被改变的东西,最常见的就是数学函数和常数

修饰类时:为最终类,任何类不能继承它

修饰函数:为最终方法,继承它的方法不能去重写它

修饰变量:终态变量,一旦初始化不能改变值

5. Java 中的 Math.round(-1.5) 等于多少?

Math.round()的原理是对传入的参数+0.5之后,再向下取整返回long型,即取比它小的第一个整数或者和它相等的整数。-1

6. String 属于基础的数据类型吗?

不是,基础数据类型:数值型byte short int long 浮点型 float double 字符型 char 布尔型 Boolean,String是一个对象,是java等编程语言的字符串

7. Java 中操作字符串都有哪些类?它们之间有什么区别?

String StringBuffer StringBuilder

String是不可变的对象,对每次String类型的改变都会生成一个新的对象,StringBufer和StringBuilder是可以改变对象的

效率:操作效率StringBuilder》Stringbuffer》String

线程安全:StringBuffer是线程安全,用于多线程,Stringbuilder是非线程安全,用于单线程

         不频繁的字符串操作使用String,反之,Stringbuffer和Stringbuilder都优于String

线程安全是多线程编程时的计算机程序代码中的一个概念。

在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。

线程安全问题大多是由全局变量静态变量引起的,局部变量逃逸也可能导致线程安全问题。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

8. String str="i" String str=new String(i)一样吗?

不一样,非一个对象

9. 如何将字符串反转?
 

public class main{

         public static void main(string[] args){

                   String s1 =’addfdfd;

                   System.out.println(new StringBuilder(s1).reverse().toString())

}

}

public class main{

public static void main(String[] args){

         string s =’5465’;

         String [] s1 = s.split(“”);

         List<String > list  = Arrays.asList(s1);

Collections.reverse(list);

system.out.println(list);

}


}

10. String 类的常用方法都有那些?

equals():字符串比较

indexOf():返回指定索引处的字符,-1

replace():替换

trim():去除字符串两端空白

split():分割为数组

getBytes():返回字符串的byte类型数组

toLowerCase():将字符串变为小写字母

toUpperCase():转为大写

substring():截取

 

11. 抽象类必须要有抽象方法吗?

不需要,抽象类不一定非要有抽象方法

abstract class cat{

         public static void sayHi(){

                   system.out.println(12);

}

}

但是即使这个类中没有抽象方法,它也不能实例化,即不能直接构造一个该类的对象,如果一个类中有了一个抽象 方法,那么这个类必须声明为抽象类,否则编译通不过

 

12. 普通类和抽象类有哪些区别?

普通类不能包含抽象方法,抽象类可以包含抽象方法

抽象类不能直接实例化,普通类可以直接实例化

 

13. 抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为final该类就不能被继承,彼此矛盾,所以final不能修饰抽象类,编辑器会提示错误:illegal combination of modifiers:‘abstract’and ‘final

 

14. 接口和抽象类有什么区别?

实现:抽象类的子类用extends来继承,接口必须使用implements来实现接口

构造函数:抽象类可以有构造函数,接口不能有

main方法:抽象类可以有main方法,并且能运行,接口不能有main方法

实现数量:类可以实现很多个接口,但是只能继承一个抽象类

访问修饰符:接口中的方法默认使用public修饰,抽象类中的方法可以任意访问修饰符

 

 

15. Java IO 流分为几种?

按功能:输入流 输出流

按类型:字节流和字符流

字节流和字符流的区别是:字节流按8位传输以字节为单位输入输出数据,字符流按16位传输以字符为单位输入输出数据

 

16. BIONIOAIO 有什么区别?

BIO:Block IO同步阻塞式IO,传统IO,模式简单,并发处理能力低

NIO:New IO同步非阻塞IO,是传统IO的升级,客户端和服务器端通过Channel通道通讯,实现了多路复用

AIO:Asynchronous IO,NIO的升级,也叫NIO2

,实现了异步非堵塞IO,异步IO的操作基于事件和回调机制

17. Files的常用方法都有哪些?

Files.exists();检测文件路径是否存在

Files.createFile(;创建文件

Files.createDirectory();创建文件夹

Files.delete() 删除文件或者目录

Files.copy()

Files.move()

Files.size()

Files.read()

Files.write()

 

二、容器

18. Java 容器都有哪些?

Java容器类库定义了两个不同概念的容器,Collection 和 Map。

Collection:

         一个独立元素的序列,这些元素都服从一条或者多头规则。其中List必须按照插入的顺序保存元素,set不能有重复的元素,List和Set继承collection接口

         collection接口常用方法:

Map:

19. Collection Collections 有什么区别?

         collection是java.util下的接口,各种集合结构的父接口, Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。

collections是java.util下的类,包含有各种集合操作的静态方法

20. ListSetMap 之间的区别是什么?

LIST和set继承自collection,Map是一个接口

List

可以允许重复的对象

可以插入多个null元素

List是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序

常用的实现类有ArrayList,linkedList、vector,其中ArrayList最为流行,它提供了使用索引的随意访问,LinkedList则对于经常需要从list中添加删除的场合更为合适

 

Set

不允许重复

只可以插入一个null元素

是一个无序容器,无法保证每个元素的存储顺序,Treeset通过Comparator或者Comparable维护了一个排序顺序

Set接口最流行的几个实现类是HashSet,linkedHashSet、TreeSet。最为流行的是基于HashMap实现的HashSet,TreeSet还实现了SortedSet接口,因此TreeSet是一个根据compare()和compareTo()的定义进行排序的有序容器

 

 

Map

Map不是collection的子接口或者实现类,Map是一个接口

Map的每个Entry都持有两个对象,也就是一个键一个值,Map可能会持有相同的值对象但键对象必须是唯一的

TreeMap也通过Comparator或者Comparable维护一个排序顺序

Map里你可以随意拥有多个null值但是只能有一个null

Map流行的几个实现类HashMap、LinkedHashMap、HashTable和TreeMap

 

21. HashMap Hashtable 有什么区别?

主要区别线程安全性、同步性、速度

线程安全性:HashTable是线程安全的,HashMap是线程不安全的

HashTable实现线程安全的方式是修改数据时      锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化。

HashTable底层数组+链表实现,无论key还是value都不能为null,初始size = 11,扩容:newsie

= oldsize*2+1

HashMap可以存储null建和null值,线程不安全,初始size为16,扩容newsize = oldSIze*2,size为2的n次幂

同步:Hashtable是线程安全的,它的方法是同步的,可以直接用在多线程环境中。而HashMap则不是线程安全的,在多线程环境中,需要手动实现同步机制。

HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);

速度:由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

 

22. 如何决定使用 HashMap 还是 TreeMap

TreeMap<K,V>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照Key值升序排序的;TreeMap的实现也是基于红黑树结构。

而HashMap<K,V>的Key值实现散列hashCode(),分布是散列的均匀的,不支持排序;数据结构主要是桶(数组),链表或红黑树。

大多情况下HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap.

 

23. 说一下 HashMap 的实现原理?

   HashMap由数据和链表组成,数组是hashmap的主体,链表主要是解决哈希冲突而存在的,如果定位到的数组位置不含链表,那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为o,首先遍历链表,存在即覆盖;对于查找操作来讲,还需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMAp中的链表出现越少,性能才会越好。

https://www.cnblogs.com/xiarongjin/p/8310011.html

24. 说一下 HashSet 的实现原理?

HashSet实际上是一个HashMap实例,都是一个存放链表的数组。它不保证存储元素的迭代顺序;此类允许使用null元素。HashSet中不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个固定对象private static final Object PRESENT = new Object();

HashSet中add方法调用的是底层HashMap中的put()方法,而如果是在HashMap中调用put,首先会判断key是否存在,如果key存在则修改value值,如果key不存在这插入这个key-value。而在set中,因为value值没有用,也就不存在修改value值的说法,因此往HashSet中添加元素,首先判断元素(也就是key)是否存在,如果不存在这插入,如果存在着不插入,这样HashSet中就不存在重复值。

 所以判断key是否存在就要重写元素的类的equals()和hashCode()方法,当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算次对象的哈希值,此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,若已有对象则通过对象所在类的equals()比较两个对象是否相同,相同则不能被添加。

   iterator:返回对此set中元素进行迭代的迭代器
     size:返回此set中元素的数量(set的容量)
     isEmpty:判断Hashset集合是否为空
     contains:判断某个元素是否存在于HashSet中
     add():如果此set中尚未包含指定元素,则添加指定元素

https://blog.csdn.net/qq_41026809/article/details/90449073

25. ArrayList LinkedList 的区别是什么?

     ArrayList使用了数组的实现,封装了对内部数组的操作
     linkedList使用了循环双向链表数据结构

26. 如何实现数组和 List 之间的转换?

List转数组:toArray(arraylist.size()方法

List<String> arrayList = new ArrayList<String>();

 arrayList.add("s");

  arrayList.add("e");

  arrayList.add("n");

  /**

   * ArrayList转数组

   */

  int size=arrayList.size();

  String[] a = arrayList.toArray(new String[size]);



/**

 * 数组转list

 */

List<String> list=Arrays.asList(a);/**

  * list转Arraylist

*/

 List<String> arrayList2 = new ArrayList<String>();

 arrayList2.addAll(list);

 System.out.println(list);

27. ArrayList Vector 的区别是什么?

1)  Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
2) 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。

28. Array ArrayList 有何区别?

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。

Array大小是固定的,ArrayList的大小是动态变化的。

ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

 

29. Queue poll() remove()有什么区别?

remove() 和 poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null。因此新的方法更适合容易出现异常条件的情况。

add()offer()区别:

add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。因此就可以在程序中进行有效的判断!

 

 

30. 哪些集合类是线程安全的?

Vector:就比Arraylist多了个同步化机制(线程安全)。

Hashtable:就比Hashmap多了个线程安全。

ConcurrentHashMap:是一种高效但是线程安全的集合。

Stack:栈,也是线程安全的,继承于Vector

 

31. 迭代器 Iterator 是什么?

https://blog.csdn.net/chenssy/article/details/37521461

对 Collection 进行迭代的类,称其为迭代器。迭代其实我们可以简单地理解为遍历,是一个标准化遍历各类容器里面的所有对象的方法类,它是一个很典型的设计模式。Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。

32. Iterator 怎么使用?有什么特点?

Iterator iterator = list.iterator();

        while(iterator.hasNext()){

            String string = iterator.next();

            //do something

        }

hasNext():如果迭代器指向位置后面还有元素,则返回 true,否则返回false

next():返回集合中Iterator指向位置后面的元素

remove():删除集合中Iterator指向位置后面的元素

 

33. Iterator ListIterator 有什么区别?

Iterator迭代器包含的方法有:

hasNext():如果迭代器指向位置后面还有元素,则返回 true,否则返回false

next():返回集合中Iterator指向位置后面的元素

remove():删除集合中Iterator指向位置后面的元素

ListIterator迭代器包含的方法有:

add(E e): 将指定的元素插入列表,插入位置为迭代器当前位置之前

hasNext():以正向遍历列表时,如果列表迭代器后面还有元素,则返回 true,否则返回false

hasPrevious():如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false

next():返回列表中ListIterator指向位置后面的元素

nextIndex():返回列表中ListIterator所需位置后面元素的索引

previous():返回列表中ListIterator指向位置前面的元素

previousIndex():返回列表中ListIterator所需位置前面元素的索引

remove():从列表中删除next()或previous()返回的最后一个元素(有点拗口,意思就是对迭代器使用hasNext()方法时,删除ListIterator指向位置后面的元素;当对迭代器使用hasPrevious()方法时,删除ListIterator指向位置前面的元素)

set(E e):从列表中将next()或previous()返回的最后一个元素返回的最后一个元素更改为指定元素e

一.相同点

都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。

二.不同点

1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。

2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。

3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。

4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

 

34. 怎么确保一个集合不能被修改?

将参数中的List返回一个不可修改的List

Collections的静态方法unmodifiableList可以达到目的。方法原型为:public static <T> List<T> unmodifiableList(List<? extends T> list);用法也很简单,传入一个List实例la,返回这个list的只读视图lb,类型依然是List。之后对lb进行add、remove等改变其内容的操作将导致编译不通过。

https://blog.csdn.net/cilen/article/details/7744969

Student1类,仅对外提供的getCourses()方法,而没有setCourses()方法,而且

通过getCourses()方法获得的courses是“只读的”,如果你试图向其添加一个新课程,则

抛出java.lang.UnsupportedOperationException。你必须通过Student1.addCourse()

向特定的Student1对象添加一个新课程。就好像,你必须让顾客自己向购物车里放食物,

而不能在顾客毫不知情下,偷偷向其购物车里放食物。

 

 

三、多线程

35. 并行和并发有什么区别?

并发,是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序。

并行,是每个cpu运行一个程序。简而言之就是并发是多个事件在同一时间段执行,而并行是多个事件在同一时间点执行。(请仔细品味以上两个图)打个比方。并发,就像一个人(cpu)喂2个孩子(程序),轮换着每人喂一口,表面上两个孩子都在吃饭。并行,就是2个人喂2个孩子,两个孩子也同时在吃饭。

 

 

 

36. 线程和进程的区别?什么是线程安全

进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

线程:是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。

一个程序至少一个进程,一个进程至少一个线程。

进程线程的区别:

    地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。

    资源拥有:同一进程内的线程共享本进程的资源如内存、I/Ocpu等,但是进程之间的资源是独立的。

     一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程

    执行过程:每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    线程是处理器调度的基本单位,但是进程不是。

两者均可并发执行。

线程安全是多线程编程时的计算机程序代码中的一个概念。

在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。

线程安全问题大多是由全局变量静态变量引起的,局部变量逃逸也可能导致线程安全问题。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

37. 守护线程是什么?

守护线程(即daemon thread),是个服务线程,准确地来说就是服务其他的线程,这是它的作用——而其他的线程只有一种,那就是用户线程。所以java里线程分2种,

1、守护线程,比如垃圾回收线程,就是最典型的守护线程。

2、用户线程,就是应用程序里的自定义线程。

 

 

38. 创建线程有哪几种方式?

 

1. 继承 Thread 类,然后调用 start 方法。

class SampleThread extends Thread {

    //重写run方法,线程运行后,跑的就是run方法

    public void run(){

       //System.out.println("");

    }

 

    public static void main(String[] args){

       Thread t1 = new SampleThread();

       Thread t2 = new SampleThread();

       t1.start();  //线程运行,调用的 run()方法.

       t2.start(); //线程运行,调用的 run()方法.. 

    }

}

2. 实现 Runnable 接口的 run 方法, 然后再用 Thread 类包裹后,调用 start 方法。

 

class A implements Runnable{

    @Override

    public void run() {

        // implement run method here

    }

 

    public static void main() {

        final A obj = new A();

 

        Thread t1 = new Thread(new A());

 

        t1.start();

    }

 

}

 

39. 说一下 runnable callable 有什么区别?

相同点:两者都是接口,都需要调用Thread.start()

不同:实现callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程不能返回结果

callable接口的call()方法允许抛出异常,而runnable()接口的run()方法的异常只能在内部消化,不能继续上抛;

40. 线程有哪些状态?

新建new新创建了一个线程对象。

可运行runnable线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

运行running可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

阻塞blocked阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种: 

死亡dead

41. sleep() wait() 有什么区别?

sleep():当前线程会放弃cpu,但是不会放弃同步锁

wait(): 当前线程放弃cpu同时会放弃互斥锁

sleep():方法是线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象。

wait()wait()Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notifynotifyAll方法来唤醒等待的线程

 

42. notify() notifyAll()有什么区别?

如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

 

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只有一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。

 

优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁

43. 线程的 run() start()有什么区别?

run():只是调用方法

start():开启一个线程每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。

start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。

 

run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。

44. 创建线程池有哪几种方式?

. newFixedThreadPool(int nThreads)

创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

. newCachedThreadPool()

创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

. newSingleThreadExecutor()

这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

. newScheduledThreadPool(int corePoolSize)

创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer

 

45. 线程池都有哪些状态?

线程池有5种状态:Running、ShutDown、Stop、Tidying、Terminated。

1. RUNNING

(01) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。

(02) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态!

道理很简单,在ctl的初始化代码中(如下),就将它初始化为RUNNING状态,并且"任务数量"初始化为0

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

2. SHUTDOWN

 (01) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。

(02) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN

3. STOP

(01) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

(02) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP

4. TIDYING

(01) 状态说明:当所有的任务已终止,ctl记录的"任务数量"0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()terminated()ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

(02) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING

当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING

5. TERMINATED

(01) 状态说明:线程池彻底终止,就变成TERMINATED状态。

(02) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED

 

46. 线程池中 submit() execute()方法有什么区别?

    接收的参数不一样

    submit有返回值,而execute没有

    submit方便Exception处理

47. Java 程序中怎么保证多线程的运行安全?

1、使用synchronied关键字,可以用于代码块,方法(静态方法,同步锁是当前字节码对象;实例方法,同步锁是实例对象)

2、使用volatile 关键字,防止指令重排,被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量

3lock锁机制

4、使用线程安全的类,比如VectorHashTableStringBuffer

线程安全在三个方面体现:

    原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);

    可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);

    有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)

49. 什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。

50. 怎么防止死锁?

死锁的四个必要条件

互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源

 

请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放

 

不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放

 

环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系

 

 

51. ThreadLocal 是什么?有哪些使用场景?

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享,java提供ThreadLocal类来支持线程局部变量,是一种实现线程安全的方式,但是在管理环境下(如web服务器)使用线程局部变量的时候要特别小心,在这种请款下,工作线程的生命周期比 任何应用变量的生命周期都要长,任何线程局部变量一旦在工作完成后没有释放,java应用就存在内存泄漏的风险。

52. 说一下 Synchronized 底层实现原理?          

java中虚拟机中的同步synchronization synchronization 基于进入和退出管程(monitor)对象实现,无论是显示同步(有明确的monitroenter和monitorexit指令,即同步代码块)还是隐式同步都是如此

synchronization可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。

java中每一个对象都可以作为锁,这是synchronization实现同步的基础:

普通同步方法,锁是当前实例对象

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

同步方法块,锁是括号里面的对象

 

53. Synchronized volatile 的区别是什么?

volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

volatile仅能使用在变量级别,synchronzed则可以使用在变量、方法、和类级别的

volatile仅能实现变量的修改可见性,不能保证原子性,而synchronized则可以保证变量的修改可见性和原子性

volatile不会造成线程的阻塞,synchronized可能会造成

volatile标记的变量不会被编译器优化,synchronized标记的变量可以被编译器优化

 

54. Synchronized Lock 有什么区别?

首先synchronized是java内置关键字,在jvm层面,Lock是个java类;

synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;

synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;

synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可);

Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题

 

55. Synchronized ReentrantLock 区别是什么?

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

 ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁

 ReentrantLock可以获取各种锁的信息

 ReentrantLock可以灵活地实现多路通知 

 

另外,二者的锁机制其实也是不一样的:ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word

56. 说一下 Atomic 的原理?

Atomic包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引用类型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。

 

Atomic系列的类中的核心方法都会调用unsafe类中的几个本地方法。我们需要先知道一个东西就是Unsafe类,全名为:sun.misc.Unsafe,这个类包含了大量的对C代码的操作,包括很多直接内存分配以及原子操作的调用,而它之所以标记为非安全的,是告诉你这个里面大量的方法调用都会存在安全隐患,需要小心使用,否则会导致严重的后果,例如在通过unsafe分配内存的时候,如果自己指定某些区域可能会导致一些类似C++一样的指针越界到其他进程的问题。

 

四、反射

 

57. 什么是反射?

         在java运行环境中,对于任意一个类,能否知道这个类有哪些属性和方法,对于任意一个对象,能否调用任意的方法

java反射机制主要提供以下功能:

         在运行时判断任意一个对象所属的类

         在运行时构造任意一个类的对象

         在运行时判断任意一个类所具有的成员变量和方法

         在运行时调用任意一个对象的方法

58. 什么是 Java 序列化?什么情况下需要序列化?

java序列化,就是把java对象变为二进制对象,便于存储和在网络上传输

什么情况下需要:

当你想把你内存中的对象状态保存到一个文件中或者数据库中的时候

当你想用套接字在网络上传送对象的时候

当你想通过RMI传输对象的时候

59. 动态代理是什么?有哪些应用?

动态代理:在运行时,创建目标类,可以调用和扩展目标类的方法。

Java 中实现动态的方式:JDK 中的动态代理 和 Java类库 CGLib

           当想要给实现了某个接口的类中的方法,加一些额外的处理,比如加日志,加事务,加权限,Spring的AOP等。

应用场景如:

 

  • 统计每个 api 的请求耗时
  • 统一的日志输出
  • 校验被调用的 api 是否已经登录和权限鉴定
  • Spring的 AOP 功能模块就是采用动态代理的机制来实现切面编程

 

60. 怎么实现动态代理?

 

https://blog.csdn.net/meism5/article/details/90413999

五、对象拷贝

61. 为什么要使用克隆?

  想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了。

62. 如何实现对象克隆?

两种不同的克隆方式,浅克隆(ShallowClone)和深克隆(DeepClone)
     两种方式:实现Cloneable接口并重写object类中的clone()方法
                     实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

63. 深拷贝和浅拷贝区别是什么?

 浅克隆只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝
     深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝

六、JAVAWEB

64. JSP servlet 有什么区别?

  jsp的本质是servlet,jvm只能识别java类,不能识别jsp的代码,web容器将jsp的代码编译成jvm额能够识别的java类
     jsp更擅长表现于页面显示,servlet更擅长于逻辑控制
     Servlet中没有内置对象,jsp的内置对象都是通过HTTPServletRequest对象,HttpServletREsponse对象以及HttpServlet对象得到的
     jsp是Servlet的一种简化,使用jsp只需完成程序员需要输出到客户端的内容,jsp中的java脚本如何镶嵌到一个类中,youjsp容器完成

65. JSP 有哪些内置对象?作用分别是什么?

     page:指的是JSP被翻译成Servlet的对象的引用
     pageContext:对象可以用来获得其他8个内置对象,还可以作为Jsp的域范围对象使用
     request:代表的是请求对象,可以用于获得客户机的信息,也可以作为域对象使用,使用request保存的数据在一次请求范围内有效
     Session:代表的是一次会话,可以用来保存用户的私有信息,也可以作为域对象使用,使用session保存的数据在一次会话范围有效
     Application:代表整个应用范围,使用这个对象保存的数据在整个web应用中都有效
     Response:是响应对象,代表的是从服务器向浏览器响应数据
     Out:jspWrite是用于向页面输出内容的对象
     Config:指的是ServletConfig用于JSP翻译成Servlet后获得Servlet的配置的对象
     Exception:在页面设置isErrorPage=“true”,即可使用,是Throwable的引用,用来获得页面错误的信息

66. 说一下 JSP 4 种作用域?

page:当前页面

session:浏览器打开到关闭

application:整个应用

request:http请求到服务器到处理结束返回响应的整个过程。

 

67. Session Cookie 有什么区别?

1.Cookie以文本文件格式存储在浏览器中,而session存储在服务器端它存储了限制数据量。它只允许4kb他没有在cookie中保存多个变量
      2.cookie的存储限制了数据量,只允许4kb,而session是无限量的
      3.我们可以轻松地访问cookie值但是我们无法轻松访问会话值,因此它更安全
      4.设置cookie时间可以使cookie过期,但是使用session-destory(),将会销毁会话

68. 说一下 Session的工作原理?

当打开浏览器到关闭浏览器,这一期间称为一个会话,也就是一个session,是保存在服务器端的,每当客户端请求页面时,服务器就会自动分配一个ID来唯一识别这个用户。一般不用session来保存大量的数据,这样会占用大量的资源

69. 如果客户端禁止 Cookie 能实现 Session 还能用吗?

       在Asp中,Session必须依赖Cookie才可用,session是存储在服务器端的,而Cookie是存储在客户端的,相对而言,session的那全性和可靠性程度都比cookie高
      在Php中通过相关额配置,可以让session不依赖Cookie而存在

70. Spring MVC Struts 的区别是什么?

1.底层实现机制:struts2是filter   springmvc是servlet
2.运行效率:struts2底层是Servlet,参数基于属性封装,如果配置单例,会出现线程安全问题,所以配置多例
                springmvc底层是servlet,单例
3.参数封装:struts2基于属性封装
                   springMvc基于方法进行封装

71. 如何避免 SQL 注入?

1.检查变量数据类型和格式
                   2.过滤特殊字符
                   3.绑定变量,使用预编译语句
      总结:使用预编译绑定变量的sql语句
               严格加密处理用户的机密信息
               不要随意开启生产环境中的webserver的错误信息
               使用正则表达式过滤传入的参数
               字符串过滤
               检查是否包含非法字

72. 什么是 XSS 攻击,如何避免?

即跨站脚本攻击,是一种常见于web应用于web应用程序中的计算机安全漏洞
1.获取用户输入,不用.innerHtml,用innerText
2.对用户输入进行过滤,如HtmlEncode函数实现应该至少进行&<>"'/等符号转义成&It&gt&quot&#x27&#x2F

73. 什么是 CSRF 攻击,如何避免?

即跨站请求伪造   
1.请求令牌
2.token验证
3.配置angular提交表头
4.再次测试跨域post

七、异常

74. throw throws 的区别?

 1.throw是在代码块内的,即在捕获方法内的异常并抛出时用的
     2.throws是针对方法的,即将方法的异常信息抛出去
     3.可以理解为throw是主动的,而throws是被动的

75. finalfinallyfinalize 有什么区别?

   final:用来修饰类,方法和变量
     finally:作为异常的处理部分,只能在try/catch语句中,表示这段语句最终一定会被执行
     finalize:是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法,该对象被回收时被调用。

76. try-catch-finally 中哪个部分可以省略?

 try语句后面必须要有一个别的语句跟在后面,如try-catch,try-finally,try-catch-finally

77. try-catch-finally 中,如果 catch return 了,finally 还会执行吗?

 会执行,在return前执行

78. 常见的异常类有哪些?

 IOEException、RunntimeException、ArrayIndexOUtOfBoundsException、NullpointerException

八、网络

79. HTTP 响应码 301 302 代表的是什么?有什么区别?

301,302都是Http状态的编码,都代表着某个URL发生了转移
     区别:    301 redirect:代表永久性转移
                  302 redirect:代表暂时性转移

80. forward redirect 的区别?

  代表了两种请求转发方式:直接转发(forward)和间接转发(redirect)
      举例:直接:A找B借钱,B说没有,B去找C借,借到借不到都会把信息传递给A
                简接:A找B借钱,B说没有,让A去找C借

81. 简述 TCP UDP 的区别?

     1.基于连接与无连接
      2.对于系统资源的要求(TCP较多,UDP少)
      3.UDP程序结构较为简单
      4.流模式与数据报模式
      5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证

82. TCP为什么要三次握手,两次不行吗?为什么?

 不行,因为为了防止已失效的连接请求又传送到服务器端,因而产生错误

83. 说一下 TCP粘包是怎么产生的?

      要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包
      接收数据端的应用层没有及时读取接收缓冲区中的数据,将会发生粘包

84. OSI 的七层模型都有哪些?

应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

85. ****Get Post 请求有哪些区别?

     Get:从指定的资源请求数据
     post:向指定的资源提交要被处理的数据

最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。

  • GET在浏览器回退时是无害的,而POST会再次提交请求

  • GET产生的URL地址可以被Bookmark,而POST不可以

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST么有。

  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。GET和POST是什么?HTTP协议中的两种发送请求的方法。

  •  

    HTTP是什么?HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。

    HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。 

    那么,“标准答案”里的那些区别是怎么回事?

在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

 

但是,我们只看到HTTP对GET和POST参数的传送渠道(url还是requrest body)提出了要求。“标准答案”里关于参数大小的限制又是从哪来的呢?

在我大万维网世界中,还有另一个重要的角色:运输公司。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司。 虽然理论上,你可以在车顶上无限的堆货物(url中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到哦。

 

好了,现在你知道,GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 

GET和POST还有一个重大区别,简单的说:

GET产生一个TCP数据包;POST产生两个TCP数据包。

 

长的说:

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

1. GET与POST都有自己的语义,不能随便混用。

2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

https://www.cnblogs.com/logsharing/p/8448446.html

86. 如何实现跨域?

https://www.cnblogs.com/fundebug/p/10329202.html

     1.图片ping或script标签跨域
     2.JSONP跨域
     3.CORS
     4.window.name+iframe
     5.window.postMessage()
     6.修改document.domain跨子域
     7.WebSocket
     8.代理

87. 说一下 JSONP 实现原理?

  浏览器只对XHR请求有同源请求限制,而对script标签src属性、link标签ref属性和img标签src属性没有这种限制,利用这个“漏洞”就可以很好的解决跨域请求。JSONP就是利用了script标签无同源限制的特点来实现的,当向第三方站点请求时,我们可以将此请求放在<script>标签的src属性里,这就如同我们请求一个普通的JS脚本,可以自由的向不同的站点请求。

九、设计模式

88. 说一下你熟悉的设计模式?

工厂方法模式,抽象工厂模式,单例工模式

89. 简单工厂和抽象工厂有什么区别?

          简单工厂就是一个专门生产某个产品的类
          抽象工厂不仅生产鼠标,同时生产键盘

十、Spring/Spring MVC

90. 为什么要使用 Spring

Spring带来了它的两大特征AOP和IOC,如果没有Spring,我们不得不在使用每一个类之前,实例化一个对象。当然我们可以用工厂方法来做这件事,就可以集中管理并且让调用者和被调用者之间的耦合松散。于是需要大量的工厂类,并且在增加或者改变接口实现的时候,还需要对工厂进行调整。而Spring就像一个大工厂一样,使用了大量的反射机制来生成需要实例的对象。
      除此以外Spring还带来了强大的代理,我们使用的每一个注入的对象都是经过代理的增强对象,同时可以使用aop包来定义一些与业务逻辑不相关的切面。增强功能模块的内聚,拆分功能模块和非业务模块。而Aop又是建立在IOC基础上,因此如果没有Spring,功能模块和非功能模块混在一起,导致逻辑混乱不清晰。

91. 解释一下什么是 AOP

面向切面编程,可以说是OOP的补充与完善。实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建方面,从而使得编译器可以在编译期间织入有关方面的代码

92. 解释一下什么是 IOC

控制反转,即借助于第三方实现具有依赖关系的对象之间的解耦

93. Spring 有哪些主要模块?

七大功能模块:
                         一、Spring Core:Core模块是Spring的核心类库,Spring的所有功能都依赖于该类库,Core主要实现IOC功能,Spring的所有功能都是借助IOC实现的。
                         二、AOP:是Spring的AOP库,提供了AOP(拦截器)机制,并提供常用的拦截器,供用户自定义和配置
                         三、ORM:提供对常用的ORM框架的管理和辅助支持,Spring支持常用的Hibernate,mybatis,jdao等框架的支持,Spring本身并不对ORM进行实现,仅对常见的ORM框架可进                   行封装,并对其进行管理。
                         四、DAO:Spring提供对JDBC的支持,对JDBC进行封装,允许JDBC使用Spring资源,并能统一管理JDBC事务,并不对JDBC进行实现。
                         五、MVC:WebMVC模块为Spring提供了一套轻量级的MVC实现,在Spring的开发中,我们既可以Struts也可以用Spring自己的MVC框架,相对于Struts,Spring自己的MVC框                   架更加简洁和方便。
                         六、WEB:常见的框架如Struts1,struts2,jsf的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器
                         七、Context:提供框架式的Bean访问方式,其他程序可以通过Context访问Spring的Bean资源,相当于资源注入。

94. Spring 常用的注入方式有哪些?

 构造方法的注入、setter注入、基于注解的注入

95. Spring 中的 Bean 是线程安全的吗?


什么是JavaBean

 

JavaBean是公共Java类,但是为了编辑工具识别,需要满足至少三个条件:

  1. 有一个public默认构造器(例如无参构造器,)
  2. 属性使用public 的get,set方法访问,也就是说设置成private,同时get,set方法与属性名的大小也需要对应。例如属性name,get方法就要写成,public String getName(){},N大写。
  3. 需要序列化。这个是框架,工具跨平台反映状态必须的

最近看<Think in Java>,里面讲到JavaBean最初是为Java GUI的可视化编程实现的.你拖动IDE构建工具创建一个GUI 组件(如多选框),其实是工具给你创建java类,并提供将类的属性暴露出来给你修改调整,将事件监听器暴露出来.《java 编程思想(第四版)》p823-824
EJB
在企业开发中,需要可伸缩的性能和事务、安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系统。 然后有提高了协议要求,就出现了Enterprise Bean。
EJB在javabean基础上又提了一些要求,当然更复杂了。
POJO
有个叫Josh MacKenzie人觉得,EJB太复杂了,完全没必要每次都用,所以发明了个POJO,POJO是普通的javabean,什么是普通,就是和EJB对应的。
总之,区别就是,你先判断是否满足javabean的条件,然后如果再实现一些要求,满足EJB条件就是EJB,否则就是POJO。

 Spring容器本身并没有提供Bean的线程安全策略
      对于线程安全问题,要从原型和单例分别说明:
            对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然不会有线程安全的问题
            对于单例Bean,如果单例Bean是一个无状态的Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。
  对于有状态的bean,Spring官方提供的bean,一般提供了通过ThreadLocal去解决线程安全的方法

96. Spring 支持几种 Bean 的作用域?

       singleton:单例模式,在整个Spring  ioc容器中,使用singleton定义的Bean将只有一个实例
       prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,将会产生一个新的Bean实例
       request:对于每次HTTP 请求,使用request定义的bean都将会产生一个新实例
       session:对于每次HTTP Session,使用session定义的bean都将产生一个新实例
       globalsession:每一个全局的HTTP Session,使用session定义的bean都将产生一个新实例

97. Spring 自动装配 Bean 有哪些方式?

 使用XML配置自动装配Bean、使用@Autowired和@Resource注解来自动装配Bean

98. Spring 事务实现方式有哪些?

     1)编程式事务管理对基于POJO的应用来说是唯一选择
     2)基于TransactionProxyFactoryBean的声明式事务管理
     3)基于@Transactional的声明式事务管理
     4)基于Aspectj AOP配置事务

99. 说一下 Spring 的事务隔离?

在一个典型的应用程序中,多个事务同时进行,经常会为了完成他们的工作而操作同一个数据。并发虽然是必须的,但会导致脏读,不可重复读和幻影读
      在理想状态下,事务之间将完全隔离,从而防止这些问题的发生。然而,完全隔离会影响性能,因为隔离经常牵扯到锁定在数据库中的记录

100. 说一下 Spring MVC 运行流程?

      1)用户发送请求到DispatchServlet(前端控制器)
       2)DispatchServlet根据请求路径查询具体的Handler
       3)HandlerMapping返回一个HandlerExcutionChain(处理程序执行链)给DispatchServlet
       4)DispatchServlet调用HandlerAdapter适配器
       5)HandlerAdapter调用具体的Handler处理业务
       6)Handler处理结束返回一个具体的ModelAndView给适配器
       7)适配器将ModelAndView给DispatchServlet
       8)DispatchServlet把视图名称给viewResolver视图解析器
       9)viewREsource返回一个具体的视图给DispatchServlet
      10)渲染视图
      11)展示给用户

101. Spring MVC 有哪些组件?

  • 前端控制器(DispatcherServlet) 
  • 处理器映射器(HandlerMapping) 
  • 处理器适配器(HandlerAdapter) 
  • 拦截器(HandlerInterceptor)
  • 语言环境处理器(LocaleResolver)
  • 主题解析器(ThemeResolver)
  • 视图解析器(ViewResolver) 
  • 文件上传处理器(MultipartResolver)
  • 异常处理器(HandlerExceptionResolver) 
  • 数据转换(DataBinder)
  • 消息转换器(HttpMessageConverter)
  • 请求转视图翻译器(RequestToViewNameTranslator)
  • 页面跳转参数管理器(FlashMapManager)
  • 处理程序执行链(HandlerExecutionChain)

102. @RequestMapping 的作用是什么?

用来处理请求地址映射的注解,可用于类和方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径

103. @Autowired 的作用是什么?

  Spring可以自动帮你把Bean里面引用的对象的Setter/getter方法省略,它会自动帮你set/get

十一、Spring Boot/Spring Cloud

104. 什么是 Spring Boot

Springboot是一个框架,一种全新的编程规范,它的产生简化了框架的使用,所谓简化是指简化了Spring众多框架中所需的大量且繁琐的配置文件,所有SpringBoot是一个服务于框架的框架,服务范围是简化配置文件

105. 为什么要用 Spring Boot

让文件配置变得相当简单、让应用部署变得简单,可以快速开启一个Web容器进行开发。

106. Spring Boot 核心配置文件是什么?

Spring Boot 中有以下两种配置文件

  • bootstrap (.yml 或者 .properties)

  • application (.yml 或者 .properties)

 

  •  

 

107. Spring Boot 配置文件有哪几种类型?它们有什么区别?

bootstrap/ application 的应用场景

application 配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。

bootstrap 配置文件有以下几个应用场景。

  • 使用 Spring Cloud Config 配置中心时,这时需要在 bootstrap 配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;

  • 一些固定的不能被覆盖的属性

  • 一些加密/解密的场景;

108. Spring Boot 有哪些方式可以实现热部署?

      Spring Loaded
      Spring-boot-devtools

109. JPA Hibernate 有什么区别?

  Hiberante是JPA规范的一个具体实现
       Hibrenate有jpa没有的特性
       Hinernate的效率更快
       JPA有更好的移植性,通用性

110. 什么是 Spring Cloud

 Spring Cloud是一个微服务框架,相比Dubbo等RPC框架,Spring Cloud提供的全套的分布式系统的解决方案
       SpringCloud对微服务基础框架Netflix的多个开源组件进行了封装,同时又实现了和云端平台以及和Spring  boot开发框架的集成
       Spring Cloud为微服务架构开发涉及的配置管理,服务治理,熔断机制,智能路由,微代理,控制总线,一次性Token,全局一致性锁,leader选举,分布式session,集群状态管理等操作提供了一种简单的开发方式
       SpringCloud为开发者提供了快速构建分布式系统的工具,开发者可以快速的启动服务和构建应用、同时能够快速和云平台进行对接。

111. Spring Cloud 断路器的作用是什么?

 为了防止在分布式系统中出现这种瀑布似的连锁反应导致的灾难

112. Spring Cloud 的核心组件有哪些?

      服务发现---Netflix  EureKa
       客服端负载均衡---Netflix Ribbon
       断路器---Netflix   Hystrix
       服务网关---Netflix Zuul
       分布式配置---Spring Cloud Config

十二、Hibernate

113. 为什么要使用 Hibernate

114. 什么是 ORM 框架?

115. Hibernate 中如何在控制台查看打印的 SQL 语句?

116. Hibernate 有几种查询方式?

117. Hibernate 实体类可以被定义为 final 吗?

118. Hibernate 中使用 Integer int 做映射有什么区别?

119. Hibernate 是如何工作的?

120. get() load()的区别?

121. 说一下 Hibernate 的缓存机制?

122. Hibernate 对象有哪些状态?

123. Hibernate getCurrentSession openSession 的区别是什么?

124. Hibernate 实体类必须要有无参构造函数吗?为什么?

十三、Mybatis

125. Mybatis #{} ${}的区别是什么?

126. Mybatis 有几种分页方式?

127. RowBounds 是一次性查询全部结果吗?为什么?

128. Mybatis 逻辑分页和物理分页的区别是什么?

129. Mybatis 是否支持延迟加载?延迟加载的原理是什么?

130. 说一下 Mybatis 的一级缓存和二级缓存?

131. Mybatis Hibernate 的区别有哪些?

132. Mybatis 有哪些执行器(Executor)?

133. Mybatis 分页插件的实现原理是什么?

134. Mybatis 如何编写一个自定义插件?

十四、RabbitMQ

135. RabbitMQ 的使用场景有哪些?

136. RabbitMQ有哪些重要的角色?

137. RabbitMQ有哪些重要的组件?

138. RabbitMQ VHost 的作用是什么?

139. RabbitMQ的消息是怎么发送的?

140. RabbitMQ怎么保证消息的稳定性?

141. RabbitMQ怎么避免消息丢失?

142. 要保证消息持久化成功的条件有哪些?

143. RabbitMQ持久化有什么缺点?

144. RabbitMQ有几种广播类型?

145. RabbitMQ怎么实现延迟消息队列?

146. RabbitMQ集群有什么用?

147. RabbitMQ节点的类型有哪些?

148. RabbitMQ集群搭建需要注意哪些问题?

149. RabbitMQ每个节点是其他节点的完整拷贝吗?为什么?

150. RabbitMQ集群中唯一一个磁盘节点崩溃了会发生什么情况?

151. RabbitMQ对集群节点停止顺序有要求吗?

十五、Kafka

152. Kafka 可以脱离 ZooKeeper 单独使用吗?为什么?

153. Kafka有几种数据保留的策略?

154. Kafka同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 Kafka将如何处理?

155. 什么情况会导致 Kafka运行变慢?

156. 使用 Kafka集群需要注意什么?

十六、ZooKeeper

157. ZooKeeper 是什么?

158. ZooKeeper都有哪些功能?

159. ZooKeeper有几种部署模式?

160. ZooKeeper怎么保证主从节点的状态同步?

161. 集群中为什么要有主节点?

162. 集群中有 3 台服务器,其中一个节点宕机,这个时候 ZooKeeper还可以使用吗?

163. 说一下 ZooKeeper 的通知机制?

十七、MySQL

164. 数据库的三范式是什么?

165. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 ID 是几?

166. 如何获取当前数据库版本?

167. 说一下 ACID 是什么?

168. Char VarChar 的区别是什么?

169. Float Double 的区别是什么?

170. MySQL 的内连接、左连接、右连接有什么区别?

171. MySQL索引是怎么实现的?

172. 怎么验证 MySQL的索引是否满足需求?

173. 说一下数据库的事务隔离?

174. 说一下 MySQL常用的引擎?

175. 说一下 MySQL的行锁和表锁?

176. 说一下乐观锁和悲观锁?

177. MySQL问题排查都有哪些手段?

178. 如何做 MySQL的性能优化?

十八、Redis

179. Redis 是什么?都有哪些使用场景?

       是由意大利人开发的一款内存高速缓存数据库。全称为远程数据服务,该软件用c语言编写,是一个key-value存储系统,支持丰富的数据类型
       众多语言都支持Redis,因为Redis交换数据快,所以在服务器中常用来存储一些需要频繁调取的数据,这样可以大大节省系统直接读取磁盘来获得数据的I/O开销,更重要的是可以极大提升速度。
拿大型网站来举个例子,比如a网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销

180. Redis有哪些功能?

慢查询、缓存

181. Redis MemeCache 有什么区别?

 1.与Memached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富的多:String、hash、List、Set和Sort Set。Redis内部使用一个redisObject对象来表示所有的key和value
      2.内存管理机制不同,并不是所有的数据都是一直存储在内存中的。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘
      3.数据持久化支持。Redis虽然是基于内存的存储系统,但它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操作的
      4.集群管理不同。memcached是全内存的数据缓冲系统,redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。

182. Redis为什么是单线程的?

  以前有个误区,认为高性能服务器一定是多线程来实现的,其实不然,redis核心就是如果我的数据全在内存里,单线程的区操作效率是最高的。因为多线程的本质就是CPU模拟出来多个线程的情况,这种模拟出来的情况就有一个代价,就是上下文的切换,对于一个内存的系统来说,它没有上下文的切换就是效率最高的。redis用单个CPU绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPu上完成的,所以它是单线程处理

183. 什么是缓存穿透?怎么解决?

  缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存

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

  String,hash,list,set,zset

185. Redis支持的 Java 客户端都有哪些?

 Redission、jedis,lettuce,官方推荐使用Redisson

186. Jedis Redisson 有哪些区别?

 Jedis时java实现redis的客户端,它的Api提供了全面类似于Redis原生命令的支持。相比于其他Redis封装框架更加原生。它的使用主要是使用JedisPool
       Redisson是一个在Redis的基础上实现的Java驻内存数据网格。它不仅提供了一系列额分布式的java常用对象,还提供了许多分布式服务

187. 怎么保证缓存和数据库数据的一致性?

我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括 合适的缓存更新策略,更新数据库后要及时更新缓存、缓存失败时增加重试机制,例如MQ模式的消息队列。

 

使用Redis作为分布式缓存,还会涉及缓存一致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效等问题。

先删除缓存中的数据,然后再去更新数据库,最后更新缓存中的数据
写请求过来,我们先删除缓存中的数据,
删除成功之后,我们再更新数据库中的数据,此时如果更新数据库中的数据失败,则整个写请求失败,直接返回,数据没有发生变化,此时读请求过来,发现缓存中没有对应的数据,则会从数据库中读取数据,同时将数据写入到缓存中,此时缓存中的数据和数据库中的数据都是一样的, 不存在数据一致性的问题
更新数据库中的数据之后 ,再来更新缓存中的数据,此时更新缓存中的数据失败,直接返回,数据库中的数据是最新的数据,开始读请求过来,发现缓存中没有对应的数据,则会从数据库中读取数据,同时将数据写入到缓存中,此时缓存中的数据和数据库中的数据都是一样的, 不存在数据一致性的问题
更新缓存成功,此时缓存中的数据和数据库的数据是一致的,不存在数据一致性的问题

乍一看,这种方案完美的解决了数据一致性的问题,我们不妨再来将业务场景复杂点,并发量再大一点,比如说每秒的读QPS为1w+,这是我们再来分析下上述方案的业务逻辑:

用户写请求过来,我们还是先删除缓存,然后再更新数据库
在更新数据库的过程中,此时更新还没有完成,数据库的值依旧是原来的旧值,这时一个读请求过来
发现缓存中没有值,就会到数据库中去查询数据,然后写入到缓存中,此时数据库还没有更新结束,读请求获取的数据依旧是原来的旧数据
这时数据库更新完成,但是更新缓存失败,此时缓存中是用的之前的旧数据与数据库中的新数据就会出现数据不一致的情况,数据一致性的问题又出现了
 

由此可见,上述的方案也是存在问题的,尤其是并发量很大的情况下,这类现象出现的几率就很大;对于这种情况我们该如何处理呢?

我们仔细分析上述的情况,可以发现,读请求和写请求是并行的,这是导致数据一致性的根本原因,并行的请求会导致数据一致性的问题,那么解决此类问题的思路就有了——将请求串行!

具体的业务逻辑如下:

写请求过来,将写请求缓存到缓存队列中,并且开始执行写请求的具体操作(删除缓存中的数据,更新数据库,更新缓存)
如果在更新数据库过程中,又来了个读请求,将读请求再次存入到缓存队列中,等待队列前的写请求执行完成,才会执行读请求
之前的写请求删除缓存失败,直接返回,此时数据库中的数据是旧值,并且与缓存中的数据是一致的,不会出现缓存一致性的问题
写请求删除缓存成功,则更新数据库,如果更新数据库失败,则直接返回,写请求结束,此时数据库中的值依旧是旧值,读请求过来后,发现缓存中没有数据, 则会直接向数据库中请求,同时将数据写入到缓存中,此时也不会出现数据一致性的问题
更新数据成功之后,再更新缓存,如果此时更新缓存失败,则缓存中没有数据,数据库中是新值 ,写请求结束,此时读请求还是一样,发现缓存中没有数据,同样会从数据库中读取数据,并且存入到缓存中,其实这里不管更新缓存成功还是失败, 都不会出现数据一致性的问题

188. Redis持久化有几种方式?

RDB与AOF两种方式

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

   1)setNx一个锁key,相应的value为当前时间加上过期时间的时钟
       2)如果setNx成功,或者当前时钟大于此时key对应的时钟则加锁成功,否则加锁失败退出
       3)加锁成功执行相应的业务操作
       4)释放锁时判断当前时钟是否小于锁key的value,如果当前时钟小于锁key对应的value对应的value则执行删除锁key的操作

190. Redis分布式锁有什么缺陷?

 对于单点的redis能很好的实现分布式锁,如果redis集群,会出现master宕机的情况。如果master宕机,此时锁key还没有同步到slave节点上,会出现机器B从新的master上获取了一个重复的锁

191. Redis如何做内存优化?

  1)redisObject对象
       2)缩减键值对象
       3)共享对象池
       4)字符串优化
       5)编码优化
       6)控制key的数量

192. Redis淘汰策略有哪些?

 

 1)voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
      
2)volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

      3)volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

      4)allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
      
5)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
      
6)no-enviction(驱逐):禁止驱逐数据

 

193. Redis常见的性能问题有哪些?该如何解决?

       1.Master写内存快照
       2.Master AOF持久化
       3.Master调用BGREWRITEAOF
       4.Redis主从复制的性能问题
       5.单点故障问题
总结:Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。
          如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
          为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。
          尽量避免在压力较大的主库上增加从库
          为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…….,这样的结构也方便解决单点故障问题,实现Slave对    Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变。

十九、JVM

194. 说一下 JVM 的主要组成部分?及其作用?

195. 说一下 JVM运行时数据区?

196. 说一下堆栈的区别?

197. 队列和栈是什么?有什么区别?

198. 什么是双亲委派模型?

199. 说一下类加载的执行过程?

200. 怎么判断对象是否可以被回收?

201. Java 中都有哪些引用类型?

202. 说一下 JVM有哪些垃圾回收算法?

203. 说一下 JVM有哪些垃圾回收器?

204. 详细介绍一下 CMS 垃圾回收器?

205. 新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

206. 简述分代垃圾回收器是怎么工作的?

207. 说一下 JVM调优的工具?

208. 常用的 JVM调优的参数都有哪些?

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页