自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(15)
  • 收藏
  • 关注

原创 什么是CAS和ABA问题?如何解决?

CAS(Compare and Swap)是一种轻量级的同步操作,也是乐观锁的一种实现,它用于实现多线程环境下的并发算法。CAS 操作包含三个操作数:内存位置(或者说是一个变量的引用)、预期的值和新值。如果内存位置的值和预期值相等,那么处理器会自动将该位置的值更新为新值,否则不进行任何操作。在多线程环境中,CAS 可以实现非阻塞算法,避免了使用锁所带来的上下文切换、调度延迟、死锁等问题,因此被广泛应用于并发编程中。

2023-06-07 07:44:00 351

原创 什么是死锁?它是如何产生的?

死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),互相持有对方所需的资源,导致它们都无法向前推进,从而导致永久阻塞的问题就是死锁。比如线程 1 拥有了锁 A 的情况下试图获取锁 B,而线程 2 又在拥有了锁 B 的情况下试图获取锁 A,这样双方就进入相互阻塞等待的情况,如下图所示:在上面的示例中,我们创建了两个锁 lock1 和 lock2,并在两个线程中分别获取这两个锁,但是获取的顺序不同。

2023-06-06 08:14:48 118

原创 synchronized和Lock有什么区别?

synchronized 可用来修饰普通方法、静态方法和代码块,当一个线程访问一个被 synchronized 修饰的方法或者代码块时,会自动获取该对象的锁,其他线程将会被阻塞,直到该线程执行完毕并释放锁。这样就保证了多个线程对共享资源的操作的互斥性,从而避免了数据的不一致性和线程安全问题。count ++;i ++) {} };try {} }Lock 是一种线程同步的机制,它与 synchronized 相似,可以用于控制对共享资源的访问。

2023-06-05 08:19:09 106

原创 为什么双重效验锁要加volatile?

单例模式的实现方法有很多种,如饿汉模式、懒汉模式、静态内部类和枚举等,当面试官问到“为什么双重效验锁要加volatile?”时,那么他指的是为什么懒汉模式中的私有变量要加 volatile?懒汉模式指的是对象的创建是懒加载的方式,并不是在程序启动时就创建对象,而是第一次被真正使用时才创建对象。要解释为什么要加 volatile?从上述代码可以看出,为了保证线程安全和高性能,代码中使用了两次 if 和 synchronized 来保证程序的执行。

2023-06-01 08:33:39 190

原创 volatile 底层是如何实现的?

原子性(Atomicity):即一个操作或者多个操作,要么全部执行,并且执行的过程不会被任何因素打断,要么都不执行。有序性(Ordering):指指令在执行过程中的顺序,一个操作执行在另一个操作之前或者在其执行之后。即程序执行的顺序按照代码的先后顺序执行。可见性(Visibility):指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

2023-05-31 08:11:37 96

原创 为什么要用线程池?

线程池是一种管理和复用线程资源的机制,它由一个线程池管理器和一组工作线程组成。线程池管理器负责创建和销毁线程池,以及管理线程池中的工作线程。工作线程则负责执行具体的任务。线程池的主要作用是管理和复用线程资源,避免了线程的频繁创建和销毁所带来的开销。线程池包含两个重要的组成部分:线程池大小:指线程池中所能容纳的最大线程数。线程池大小一般根据系统的负载情况和硬件资源来设置。工作队列:用于存放等待执行的任务。当线程池中的工作线程已经全部被占用时,新的任务将被加入到工作队列中等待执行。

2023-05-30 08:15:54 248 1

原创 线程池是如何执行的?任务太多会怎样?

/ 任务的具体方法 Runnable runnable = new Runnable() {System . out . println("当前任务被执行,执行时间:" + new Date() + " 执行线程:" + Thread . currentThread() . getName());try {// 等待 1s TimeUnit . SECONDS . sleep(1);} } };

2023-05-29 08:24:18 132 1

原创 线程是如何通讯的?

线程通讯指的是多个线程之间通过共享内存或消息传递等方式来协调和同步它们的执行。在多线程编程中,通常会出现多个线程需要共同完成某个任务的情况,这时就需要线程之间进行通讯,以保证任务能够顺利地执行。线程通讯的实现方式主要有以下两种:共享内存:多个线程可以访问同一个共享内存区域,通过读取和写入内存中的数据来进行通讯和同步。消息传递:多个线程之间通过消息队列、管道、信号量等机制来传递信息和同步状态。

2023-05-26 08:25:18 1698 1

原创 ConcurrentHashMap是如何实现的?

众所周知 ConcurrentHashMap 是 HashMap 的多线程版本,HashMap 在并发操作时会有各种问题,比如死循环问题、数据覆盖等问题。而这些问题,只要使用 ConcurrentHashMap 就可以完美解决了,那问题来了,ConcurrentHashMap 是如何保证线程安全的?它的底层又是如何实现的?

2023-05-25 08:13:42 73 1

原创 被问懵了:什么是负载因子?为什么是0.75?

前几天面试被问懵了,还是关于 HashMap 的面试题,什么是负载因子?为什么是0.75?第一个问题还好回答,然而第二个问题就有点含糊其辞说不清楚了,所以今天就来好好复盘一下这道题。HashMap 负载因子 load factor,也叫做扩容因子和装载因子,它是 HashMap 在进行扩容时的一个阈值,当 HashMap 中的元素个数超过了容量乘以负载因子时,就会进行扩容。默认的负载因子是 0.75,也就是说当 HashMap 中的元素个数超过了容量的 75% 时,就会进行扩容。

2023-05-24 08:15:07 1562 2

原创 为什么 HashMap 会死循环?

头插法是指新来的值会取代原有的值,插入到链表的头部,如下图所示。原链表如下图所示:此时使用头插入插入一个元素 Z,如下图所示:头插法会导致 HashMap 在进行扩容时,链表的顺序发生反转,如下图所示:因为在 HashMap 扩容时,会先从旧 HashMap 的头节点读取并插入到新 HashMap 节点中,旧节点的读取顺序是 A -> B -> C,于是插入到新 HashMap 中的顺序就变成了 C -> B -> A,这样就破坏了链表的顺序,导致了链表反转。

2023-05-23 08:18:12 564 1

原创 面试复盘:哈希冲突的常见解决方案?

Java 面试中不可能不问 HashMap,问到 HashMap 就会问到哈希冲突的解决方案,相信很多人也遇到过了,所以这里就详细的总结复盘一下。哈希冲突是指在哈希表中,两个或多个元素被映射到了同一个位置的情况。程序的运行结果如下:不同的字符串,却拥有了相同的 hashCode 这就是哈希冲突。因为元素的位置是根据 hashCode 的值进行定位的,此时它们的 hashCode 相同,但一个位置只能存储一个值,这就是哈希冲突。

2023-05-22 08:26:59 356 1

原创 HashMap 底层是如何实现的?

HashMap 在不同的 JDK 版本下的实现是不同的,在 JDK 1.7 时,HashMap 底层是通过数组 + 链表实现的;而在 JDK 1.8 时,HashMap 底层是通过数组 + 链表或红黑树实现的。具体来说,HashMap 内部维护了一个数组,每个数组元素又是一个链表或者红黑树,每个链表或者红黑树节点存储了一个键值对。当需要存储新的键值对时,HashMap 会根据键的哈希值确定其在数组中的位置,如果该位置已经有了其他键值对,则通过链表或红黑树解决冲突,将新的键值对添加到链表或红黑树的末尾。

2023-05-19 07:49:06 250 1

原创 什么是反射?它有什么用?

在 Java 中,反射是指在运行时检查和操作类、接口、字段、方法等程序结构的能力。通过反射,可以在运行时获取类的信息,创建类的实例,调用类的方法,访问和修改类的字段等。

2023-05-18 08:36:38 97 1

原创 抽象类和接口有什么区别?

java面试突击

2023-05-16 09:40:26 105

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除