java面试题及答案2024,java2024最新面试题及答案(之一)

发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全,希望对大家有帮助哈~

本套Java面试题大全,全的不能再全,哈哈~

一、Java 基础

1. JDK 和 JRE 有什么区别?

  • JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
  • JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。

具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。

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

== 解读

对于基本类型和引用类型 == 的作用效果是不同的,如下所示:

  • 基本类型:比较的是值是否相同;
  • 引用类型:比较的是引用是否相同;

代码示例:

String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true

代码解读:因为 x 和 y 指向的是同一个引用,所以 == 也是 true,而 new String()方法则重写开辟了内存空间,所以 == 结果为 false,而 equals 比较的一直是值,所以结果都为 true。

equals 解读

equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。看下面的代码就明白了。

首先来看默认情况下 equals 比较一个有相同值的对象,代码如下:

class Cat {public Cat(String name) {this.name = name;}private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}Cat c1 = new Cat("王磊");
Cat c2 = new Cat("王磊");
System.out.println(c1.equals(c2)); // false

输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:

public boolean equals(Object obj) {return (this == obj);
}

原来 equals 本质上就是 ==。

那问题来了,两个相同值的 String 对象,为什么返回的是 true?代码如下:

String s1 = new String("老王");
String s2 = new String("老王");
System.out.println(s1.equals(s2)); // true

同样的,当我们进入 String 的 equals 方法,找到了答案,代码如下:

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

原来是 String 重写了 Object 的 equals 方法,把引用比较改成了值比较。

总结 :== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

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

不对,两个对象的 hashCode()相同,equals()不一定 true。

代码示例:

String str1 = "通话";
String str2 = "重地";
System.out.println(String.format("str1:%d | str2:%d",  str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));

执行的结果:

str1:1179395 | str2:1179395

false

代码解读:很显然“通话”和“重地”的 hashCode() 相同,然而 equals() 则为 false,因为在散列表中,hashCode()相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。

4. final 在 java 中有什么作用?

  • final 修饰的类叫最终类,该类不能被继承。
  • final 修饰的方法不能被重写。
  • final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。

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

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

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

String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。

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

操作字符串的类有:String、StringBuffer、StringBuilder。

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

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

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String("i") 则会被分到堆内存中。

9. 如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

示例代码:

// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("abcdefg");
System.out.println(stringBuffer.reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abcdefg");
System.out.println(stringBuilder.reverse()); // gfedcba

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

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。

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

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

示例代码:

abstract class Cat {public static void sayHi() {System.out.println("hi~");}
}

上面代码,抽象类并没有抽象方法但完全可以正常运行。

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

  • 普通类不能包含抽象方法,抽象类可以包含抽象方法。
  • 抽象类不能直接实例化,普通类可以直接实例化。

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

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类,如下图所示,编辑器也会提示错误信息:

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

  • 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
  • 构造函数:抽象类可以有构造函数;接口不能有。
  • main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
  • 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
  • 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。

15. java 中 IO 流分为几种?

按功能来分:输入流(input)、输出流(output)。

按类型来分:字节流和字符流。

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

16. BIO、NIO、AIO 有什么区别?

  • 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 容器都有哪些?

常用容器的图录:

19. Collection 和 Collections 有什么区别?

  • java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
  • Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

20. List、Set、Map 之间的区别是什么?

21. HashMap 和 Hashtable 有什么区别?

  • hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
  • hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
  • hashMap允许空键值,而hashTable不允许。

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

对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。

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

HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 

HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

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

  • HashSet底层由HashMap实现
  • HashSet的值存放于HashMap的key上
  • HashMap的value统一为PRESENT

25. ArrayList 和 LinkedList 的区别是什么?

最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。

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

  • List转换成为数组:调用ArrayList的toArray方法。
  • 数组转换成为List:调用Arrays的asList方法。

27. ArrayList 和 Vector 的区别是什么?

  • Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。 
  • ArrayList比Vector快,它因为有同步,不会过载。 
  • ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。

28. Array 和 ArrayList 有何区别?

  • Array可以容纳基本类型和对象,而ArrayList只能容纳对象。 
  • Array是指定大小的,而ArrayList大小是固定的。 
  • Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

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

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

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

  • vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
  • statck:堆栈类,先进后出。
  • hashtable:就比hashmap多了个线程安全。
  • enumeration:枚举,相当于迭代器。

31. 迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

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

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

33. Iterator 和 ListIterator 有什么区别?

  • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。 
  • Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。 
  • ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

 三、多线程

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

  • 并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
  • 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
  • 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务。如hadoop分布式集群。

所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。

36. 线程和进程的区别?

简而言之,进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。

37. 守护线程是什么?

守护线程(即daemon thread),是个服务线程,准确地来说就是服务其他的线程。

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

①. 继承Thread类创建线程类

  • 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
  • 创建Thread子类的实例,即创建了线程对象。
  • 调用线程对象的start()方法来启动该线程。

②. 通过Runnable接口创建线程类

  • 定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
  • 创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
  • 调用线程对象的start()方法来启动该线程。

③. 通过Callable和Future创建线程

  • 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
  • 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
  • 使用FutureTask对象作为Thread对象的target创建并启动新线程。
  • 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

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

有点深的问题了,也看出一个Java程序员学习知识的广度。

  • Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;
  • Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。

40. 线程有哪些状态?

线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。

  • 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
  • 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
  • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
  • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
  • 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪   

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

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

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

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

  • 如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。
  • 当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争。
  • 优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

43. 线程的 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。

线程池各个状态切换框架图:

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

  • 接收的参数不一样
  • submit有返回值,而execute没有
  • submit方便Exception处理

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

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

  • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
  • 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
  • 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。

48. 多线程锁的升级原理是什么?

在Java中,锁共有4种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。

锁升级的图示过程: 

49. 什么是死锁?

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

50. 怎么防止死锁?

死锁的四个必要条件:

  • 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
  • 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
  • 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
  • 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。

所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算法,避免进程永久占据系统资源。

此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。

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

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

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

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

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

  • 普通同步方法,锁是当前实例对象
  • 静态同步方法,锁是当前类的class对象
  • 同步方法块,锁是括号里面的对象

53. synchronized 和 volatile 的区别是什么?

  • volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  • volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
  • 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++一样的指针越界到其他进程的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

03_03_初识SpringAOP和应用

一、SpringAOP的初识与原理 1、概述 AOP:面向切面编程OOP:面向对象编程面相切面编程:是基于OOP基础之上的新编程思想,OOP面向的主要是对象是类,而AOP面向的主要对象是切面,它在处理日志、安全管理、事务管…

结账和反结账

结账与反结账功能在财务软件和会计系统中扮演着重要的角色,以下是关于这两个功能的详细解释: 一、结账功能 结账功能是计算和结转各个会计科目本期发生额和期末余额的过程,同时标志着一定时期内财务活动的结束和财务数据的固化。结账功能的…

C语言 链表经典OJ题

链表经典OJ题 移除链表元素链表的中间节点反转链表合并两个有序链表分割链表 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head […

python小练习03

1.绘制奥运五环旗 #奥运五环的绘制 import turtle as t t.pensize(3) t.speed(0) def draw_circles():i0while i <4:args [[-60,0,"blue"],[0,0,"black"],[60,0,"red"],[-30,-30,"yellow"],[30,-30,"green"]]#定义一个…

lua vm 二: 查看字节码、看懂字节码

本文讲一讲如何查看 lua 的字节码&#xff08;bytecode&#xff09;&#xff0c;以及如何看懂字节码。 以下分析基于 lua-5.4.6&#xff0c;下载地址&#xff1a;https://lua.org/ftp/ 。 1. 查看字节码 1.1 方法一&#xff1a;使用 luac luac 是 lua 自带的编译程序&#x…

MySQL(三) - 基础操作

一、索引 由于我们在使用数据库的时候&#xff0c;大部分操作的都是查询操作&#xff0c;但是我们每一次进行查询都需要遍历一遍表中所有数据&#xff0c;这会花费O(n)的时间&#xff0c;因此数据引入了“索引” 也就是在底层使用了数据结构来进行优化查询的操作&#xff0c;但…

【TB作品】MSP430F149单片机,广告牌,滚动显示

LCD1602滚动显示切换播放暂停字符串 显示Public Places 显示No Smoking 播放 暂停 部分代码 char zifu1[] "Public Places "; char zifu2[] "Class Now "; char zifu3[] "No admittance "; char *zifu[] { zifu1, zifu2, zifu3 }…

优思学院|客户质量工程师CQE岗位的未来发展,你怎么看?

在现代工业的发展背景下&#xff0c;客户质量工程师&#xff08;CQE&#xff09;正逐渐成为企业质量管理体系中的关键角色。随着全球化和数字化的不断推进&#xff0c;CQE的职责不仅限于传统的质量控制&#xff0c;更包括了质量管理体系的设计和优化、客户关系的管理、以及在整…

【UML用户指南】-06-面向对象建模-关系(relationship)

目录 1、面向对象建模常见的关系 2、关系的组成元素 3、依赖关系 4、泛化关系 5、关联关系 关联的四种修饰 1.名称 2.角色 3.多重性 4.聚合 6、常用建模技术 6.1、对简单依赖建模 6.2、对单继承建模 6.3、对结构关系建模 1、面向对象建模常见的关系 依赖 &#x…

pyqt绘制各种直线

pyqt绘制各种直线 介绍效果代码 介绍 使用pyqt绘制各种直线 效果 代码 import sys from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtGui import QPainter, QPen, QPainterPath, QColor, QBrush from PyQt5.QtCore import Qt, QPoint, QLineF, QPointFclass…

JVM 指针压缩

运用java内存对齐填充&#xff0c;对java内存进行8字节划分&#xff0c;java对象指针映射到每个划分区域上&#xff0c;使得4个字节&#xff08;32位&#xff09;表示2^32个地址&#xff0c;从而使4个字节指针映射32G内存空间。 1.为什么进行指针压缩&#xff1a; jvm从32位变…

【全开源】Java代驾小程序APP代驾跑腿源码微信小程序代驾源码

&#x1f697;代驾小程序&#xff1a;便捷、安全的出行新选择 一、引言&#xff1a;出行新风尚 在如今繁忙的都市生活中&#xff0c;出行问题一直是人们关注的焦点。代驾小程序的出现&#xff0c;为我们提供了一种便捷、安全的出行新选择。无论是酒后不能驾车&#xff0c;还是…

牛客网刷题 | BC116 [NOIP2013]记数问题

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 试计算在区间1 到n…

LeetCode:环形链表II

文章收录于LeetCode专栏 LeetCode地址 环形链表II 题目 给定一个链表&#xff0c;返回链表开始入环的第一个节点。如果链表无环&#xff0c;则返回null。   为了表示给定链表中的环&#xff0c;我们使用整数pos来表示链表尾连接到链表中的位置&#xff08;索引从0开始&#…

安防监控视频平台LntonCVS视频监控汇聚平台遏制校园暴力保护校园学生安全应用方案

未成年人被誉为祖国的花朵&#xff0c;是我们国家的未来。然而&#xff0c;最近频繁曝出的未成年霸凌事件却引发了社会的广泛关注。这些事件手段残忍&#xff0c;事态恶劣&#xff0c;引发了全社会对如何保护未成年身心健康、规避霸凌事件发生的深刻思考。 为了更好地保障学生的…

使用软件分享--剪映(不需要会员版)剪映 Jianying_pro_3_2_0_8778_beta9_jianyingpro_beta(Windows)

专栏介绍&#xff1a;本专栏主要分享一些实用的软件&#xff08;Po Jie版&#xff09;&#xff1b; 声明1&#xff1a;软件不保证时效性&#xff1b;只能保证在写本文时&#xff0c;该软件是可用的&#xff1b;不保证后续时间该软件能一直正常运行&#xff1b;不保证没有bug&am…

深度学习-06-手动进行反向传播

深度学习-06-手动进行反向传播 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xf…

【网关】工业智能网关-02

一 公司简介 保定飞凌嵌入式技术有限公司始于2006年&#xff0c;是一家专注嵌入式核心控制系统研发、设计和生产的高新技术企业&#xff0c;是国内最早专业从事嵌入式技术的企业之一。 经过十几年的发展与积累&#xff0c;公司拥有业内一流的软硬件研发团队&#xff0c;在北京…

SuperMap GIS基础产品FAQ集锦(20240603)

一、SuperMap iDesktopX 问题1&#xff1a;请教一下&#xff0c;桌面把火星坐标系的数据投影转换为4326坐标系数据如何才能没有偏移呢&#xff1f; 11.1.1 【解决办法】可以使用iDesktopX提供的“电子地图坐标转换”插件实现对火星坐标系数据的纠偏。 问题2&#xff1a;请教…

麦肯锡:ChatGPT等生成式AI应用激增,大中华区增长最快

全球顶级咨询公司麦肯锡&#xff08;McKinsey & Company&#xff09;在官网发布了《he state of AI in early 2024:Gen AI adoption spikes and starts to generate value》&#xff0c;一份关于生成式AI应用的调查报告。 麦肯锡对多个国家/地区的1,363位管理者进行了调查…