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. 如何实现对象克隆?

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

六、JAVAWEB

64. JSP servlet 有什么区别?

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

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

page:当前页面

session:浏览器打开到关闭

application:整个应用

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

 

67. Session Cookie 有什么区别?

 

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

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

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

71. 如何避免 SQL 注入?

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

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

七、异常

74. throw throws 的区别?

75. finalfinallyfinalize 有什么区别?

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

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

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

八、网络

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

80. forward redirect 的区别?

81. 简述 TCP UDP 的区别?

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

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

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

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

86. 如何实现跨域?

87. 说一下 JSONP 实现原理?

九、设计模式

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

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

十、Spring/Spring MVC

90. 为什么要使用 Spring

91. 解释一下什么是 AOP

92. 解释一下什么是 IOC

93. Spring 有哪些主要模块?

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

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

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

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

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

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

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

101. Spring MVC 有哪些组件?

102. @RequestMapping 的作用是什么?

103. @Autowired 的作用是什么?

十一、Spring Boot/Spring Cloud

104. 什么是 Spring Boot

105. 为什么要用 Spring Boot

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

 

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

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

109. JPA Hibernate 有什么区别?

110. 什么是 Spring Cloud

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

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

十二、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 是什么?都有哪些使用场景?

180. Redis有哪些功能?

181. Redis MemeCache 有什么区别?

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

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

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

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

186. Jedis Redisson 有哪些区别?

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

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

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

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

191. Redis如何做内存优化?

192. Redis淘汰策略有哪些?

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

十九、JVM

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

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

196. 说一下堆栈的区别?

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

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

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

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

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

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

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

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

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

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

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

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

 

发布了26 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_22062405/article/details/103400240