Java
文章平均质量分 69
Java基础知识
山水有相逢2023
做一个热爱分享、会写作的程序员
展开
-
CycliBarrier原理解释
这个方法会检查当前屏障代是否已经被打破(broken),然后将等待的线程计数器减一。当最后一个线程到达时,它会触发屏障,并通知所有在条件变量上等待的线程。是 Java 并发编程中的一个同步辅助工具,它允许一组线程相互等待,达到一个公共屏障点(Barrier Point),然后这些线程才继续执行。这个锁用于控制对屏障状态的访问,条件变量用于挂起线程直到所有线程都到达屏障。,而是使用了一个内部锁和条件变量来实现类似的等待/通知机制。被调用,这通常发生在最后一个线程到达屏障时或者屏障被重置或打破时。原创 2023-12-10 22:55:02 · 195 阅读 · 0 评论 -
ThreadLocal 内存泄露问题是怎么导致的?
内存泄露问题主要是由于其使用方式不当导致的。要理解这个问题,我们需要先了解的工作原理和常见使用场景。原创 2023-12-05 07:22:27 · 243 阅读 · 0 评论 -
AQS中Condition的使用
AQS 是 Java 并发包中用于构建锁和其他同步组件的基础框架,而 Condition 对象则用于实现锁上的等待/通知模式,类似于传统的。)结合使用,允许线程有选择地进行等待和唤醒操作。这些 Condition 对象提供了等待和通知的方法,例如。当线程持有相关的锁时,它可以调用 Condition 的等待和通知方法。:通过 Condition 对象,线程可以在某个条件不满足时调用。调用时进入等待状态,直到另一个线程在条件变化后调用。方法来唤醒一个或所有等待的线程。在这个例子中,线程在。原创 2023-12-04 07:46:01 · 132 阅读 · 0 评论 -
StampedLock源码概述
在的实现中,状态(state)是一个long类型的变量,它的不同部分表示不同类型的锁。使用一系列位操作来管理和更新这个状态变量,以此来实现锁机制。写锁:通过设置特定的位来表示写锁。如果这些位被设置,意味着写锁正在被持有。读锁:通过增加状态变量的特定部分的计数来表示读锁的数量。多个线程可以同时持有读锁。乐观读锁:它不实际持有锁,而是通过检查状态变量在读取之前和之后是否发生变化来判断是否有写操作。原创 2023-12-04 07:21:00 · 69 阅读 · 0 评论 -
synchronized底层实现原理
Java中的关键字是用于实现线程同步的一种机制,它可以保证多个线程在访问共享资源时的数据一致性和防止数据竞争。的实现涉及多个层面,包括Java语言层面、Java虚拟机(JVM)层面以及操作系统层面。以下是对。原创 2023-12-03 11:26:38 · 24 阅读 · 0 评论 -
Java中共享变量的可见性,底层是由缓存一致性机制来保证的吗?
总结来说,Java程序中共享变量的可见性是通过JMM定义的高级抽象在语言层面上规定的,而在底层,它是通过CPU的缓存一致性机制来实现的。JMM的规则被设计成能够在不同的硬件架构上一致地工作,而缓存一致性机制是这些规则在硬件层面的实际实现。这里涉及两个层次的交互:Java内存模型(JMM)提供的高级抽象和底层硬件(尤其是CPU缓存)的物理实现。原创 2023-12-01 07:23:03 · 29 阅读 · 0 评论 -
缓存一致性MESI 协议
MESI 协议是一种用于保证多处理器系统中缓存一致性的协议。MESI 是 Modified(修改)、Exclusive(独占)、Shared(共享)和 Invalid(无效)四种状态的首字母缩写,这些状态描述了一个缓存行(cache line)在不同处理器缓存中的状态。MESI 协议是缓存一致性问题的一个解决方案,它确保了在多个 CPU 缓存中存储的相同内存位置的数据保持一致。原创 2023-11-30 07:29:20 · 157 阅读 · 0 评论 -
Java wait()方法之后,其他线程可以进入同步块吗?
方法的关键特性之一:它不仅使线程进入等待状态,同时也释放了它持有的锁,从而允许其他线程进入被该锁保护的同步区域。这样,其他线程可以执行它们自己的同步代码块,包括调用。得以执行,获取锁,进入同步块,打印 “Thread 2 has entered the synchronized block.”。在它的同步块结束后,锁被释放。开始执行,进入同步块,打印 “Thread 1 is waiting.”,然后调用。然后,线程 1 会尝试重新获取锁,一旦获取成功,它就会从。这使线程 2 能够获取锁并进入它的同步块。原创 2023-11-30 07:05:34 · 137 阅读 · 0 评论 -
执行Native方法时,程序计数器记录的是 undefined 地址,那线程切回来的时候怎么知道执行的是哪一行代码?
如果线程在执行 native 方法期间被中断,当它恢复执行时,会从上次离开的地方继续执行,这是由操作系统和 native 代码自身的执行环境管理的。在 Java 中,native 方法是用来执行非 Java 代码的,通常是用其他语言(如 C 或 C++)编写的,用于访问操作系统的底层资源或执行特定的系统调用。因此,尽管 JVM 在执行 native 方法时不直接管理程序计数器,但线程的执行状态(包括在 native 代码中的位置)是被保留的,允许线程在被中断后恢复执行。原创 2023-11-30 06:37:14 · 45 阅读 · 0 评论 -
ArrayDeque和LinkedList对比
ArrayDeque和LinkedList是 Java 集合框架中的两个重要类,分别代表了数组双端队列和链表。它们都实现了Deque接口,但内部结构和工作机制有很大差异。原创 2023-11-26 22:32:50 · 59 阅读 · 0 评论 -
Java SPI 机制详解
Java SPI (Service Provider Interface) 是一种服务发现机制。它允许服务提供者通过一个统一的接口向其服务的使用者提供实现,而使用者可以在运行时发现并使用这些服务。SPI机制在Java中被广泛用于提供扩展和插件功能,例如在JDBC中用于加载数据库驱动,在日志框架中用于加载具体的日志实现等。一个简单的例子是,假设有一个文本解析服务接口。那么服务提供者将在其jar包的。实现,并对给定的文本进行解析。这段代码会自动发现所有可用的。原创 2023-11-26 21:26:38 · 49 阅读 · 0 评论 -
计算机是怎么存储浮点数?浮点数运算为什么会存在丢失精度风险?
计算机中存储浮点数使用的是IEEE 754标准,这是一个国际标准,用于确保在不同的计算机和计算平台之间可以一致地表示和处理浮点数。这个标准定义了几种不同的表示方法,最常用的是单精度(32位)和双精度(64位)浮点数。:这是一个单独的位,用来表示数字的正负。0代表正数,1代表负数。:这部分用来表示数字的范围(大小)。在32位单精度浮点数中,指数占用8位;在64位双精度浮点数中,指数占用11位。指数使用偏移量或称为偏移二进制表示法,这意味着一个固定的偏移量会被加到实际的指数值上,以允许表示正负指数。原创 2023-11-22 17:06:40 · 288 阅读 · 1 评论 -
BigDecimal运算为什么不会丢失精度
会简单地将两个操作数的unscaled values相乘,并将它们的scales相加,得到结果的scale。除法是最复杂的,因为通常需要指定结果的scale以及舍入模式。通过设置scale和舍入模式,我们可以得到一个确定的结果。Java中,如果未指定舍入模式,而结果是无限循环小数的话,会自动对齐操作数的scale。减法操作类似于加法,在执行。原创 2023-11-26 16:19:33 · 176 阅读 · 0 评论 -
Java对象包含的成员变量值存放在哪个内存区?
在Java中,一个对象的成员变量(也称为实例变量)存储在堆内存(Heap Memory)区域。:这是Java虚拟机(JVM)中的一个主要区域,用于存储所有运行时创建的对象。不管这些对象是属于哪个类的实例,它们都存储在堆内存中。成员变量作为对象的一部分,随着对象一起存储在这里。:这个区域存储局部变量和方法调用。当你调用一个方法时,一个新的块被创建在栈上,用于存储局部变量和方法的参数。当方法结束时,这个块被移除。:这部分内存用于存储类结构(如运行时常量池、字段和方法数据)以及方法和构造函数的代码,包括静态变量。原创 2023-11-22 15:26:24 · 1117 阅读 · 1 评论 -
Java I/O 流为什么要分为字节流和字符流呢?
字符流通过封装字节流并处理字符编码的转换,简化了字符数据的处理。在处理文本数据时,缓冲字符流比缓冲字节流更高效,因为它们直接在字符级别上操作,而不需要开发者手动管理字符编码和字节之间的转换。因此,可以一次性从缓冲区读取多个字符,或者将多个字符写入缓冲区,这减少了I/O操作的次数,从而提升了性能。简而言之,通过区分字节流和字符流,Java提供了一种强大的机制来处理各种数据类型,同时也简化了文本处理,并且支持国际化。因此,可以说,是缓冲技术而不是字符流本身提高了性能,字符流只是提供了处理字符的便利性。原创 2023-11-25 23:00:26 · 456 阅读 · 0 评论 -
CGLIB 动态代理
CGLIB(Code Generation Library)是一个强大的,高性能,高质量的Code生成库,它可以在运行时扩展Java类和实现Java接口。它被许多其他Java框架用来提供动态代理功能,例如Spring。CGLIB包含了许多在AOP中广泛使用的功能,它比Java自带的动态代理机制要强大,因为它不仅可以代理接口,还可以代理没有接口的类。下面是使用CGLIB实现动态代理的一个例子:然后,我们定义一个,它是CGLIB动态代理的核心。是CGLIB中的一个接口,它类似于Java动态代理中的在的。原创 2023-11-26 14:31:15 · 23 阅读 · 0 评论 -
Java 类加载顺序
Java的类加载顺序涉及多个步骤,它们是按照Java虚拟机(JVM)规范来执行的。()在初始化阶段,如果这个类有父类,那么JVM会确保其父类已经被加载、验证、准备、解析和初始化。初始化阶段是执行类构造器静态代码块的部分,这通常是执行静态变量赋值和静态代码块。Object。原创 2023-11-21 23:28:24 · 251 阅读 · 0 评论 -
网络七层协议和四层协议
网络的七层协议通常指的是OSI(Open Systems Interconnection)模型,它是国际标准化组织(ISO)提出的一个网络通信模型,主要用于不同系统间的通信。这两个模型都是描述网络通信过程的方式,但TCP/IP模型更为简洁,而OSI模型更为详细。在实际应用中,TCP/IP模型由于其简洁性而被广泛采用。四层协议通常是指TCP/IP模型,它是一种更简化的网络通信模型,广泛应用于互联网。原创 2023-11-25 22:43:42 · 125 阅读 · 0 评论 -
Java的动态代理机制
Java的动态代理机制是一种非常强大的运行时代理生成方法。它允许开发者在运行时动态地创建代理类和代理对象,用于实现接口的方法。动态代理主要通过类和接口来实现。以下是一个使用Java动态代理机制的简单例子:假设有一个接口Subject和一个实现了Subject接口的类。为了创建一个动态代理,我们需要定义一个,当代理对象的方法被调用时,会转发到这个。接下来,我们可以使用Proxy类来动态地创建代理对象。在这个例子中,当调用方法时,会首先调用中的invoke方法,然后在invoke方法中调用实际对象的。原创 2023-11-26 14:17:27 · 42 阅读 · 1 评论 -
JDK 动态代理和 CGLIB 动态代理对比
JDK动态代理和CGLIB动态代理是Java中两种常见的动态代理方式,它们都用于在运行时动态地创建代理对象。原创 2023-11-26 14:44:33 · 3638 阅读 · 1 评论 -
ArrayBlockingQueue的put和take过程详解
ArrayBlockingQueue具有以下特性:1)队列是有边界的,在创建时需指定队列大小;2)队列是先进先出,从尾部进,从头部出;3)队列已满时会阻塞添加;队列为空时会阻塞获取;4)支持以公平和非公平的方式,写入和获取元素。下面从源码的角度来分析下ArrayBlockingQueue的代码实现,也就能够清晰明白ArrayBlockingQueue的特性,主要从put和take过程讲解。原创 2022-05-07 13:31:03 · 1248 阅读 · 0 评论 -
ReentrantLock之公平锁和非公平锁详解
ReentrantLock是一个互斥锁,它具有synchronized相同的能力;但相比之下,ReentrantLock扩展性更强,比如实现了公平锁。本文详细拆解了ReentrantLock的公平锁和非公平锁的实现。原创 2022-05-04 15:13:31 · 4568 阅读 · 0 评论