- 博客(130)
- 收藏
- 关注
原创 7.9 ThreadLocal
问题描述:5个销售买房子,集团只关心销售总量的准确统计数,按照总销售额统计,方便集团公司给部分发送奖金,即 5 个线程同时操作一个共享变量销售总量,为了保证数据安全,只能加锁i < 5;j++) {}, "线程" + i).start();try {System.out.println(Thread.currentThread().getName() + "\t" + "共计卖出多少套" + house.saleCount);输出结果。
2024-07-13 17:39:21
607
原创 7.8 CompletableFuture
Future 对于结果的获取不是很友好,只能通过阻塞或轮询的方式得到任务的结果。CompletableFuture 实现了 Future 接口和 CompletionStage 接口。上述没有指定Executor的方法,直接使用默认的作为它的线程池执行异步代码。如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码。try {System.out.println("1号任务\t" + Thread.currentThread().getName());try {
2024-07-13 17:38:38
746
原创 7.7 CyclicBarrier
CyclicBarrier 循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置【计数个数】。每个线程执行到某个需要“同步”的时刻调用 await() 方法进行等待,当等待的线程数满足【计数个数】时,继续执行。
2024-07-13 17:37:52
297
原创 7.6 CountdownLatch
用来进行线程同步协作,等待所有线程完成倒计时。其中构造参数用来初始化等待计数值,await() 用来等待计数归零,countDown() 用来让计数减一。输出可以配合线程池使用,改进如下输出。
2024-07-13 17:37:18
174
原创 7.4 读写锁原理
当读操作远远高于写操作时,这时候使用读写锁让读读可以并发,提高性能。类似于数据库中。提供一个数据容器类内部分别使用读锁保护数据的read(),写锁保护数据的write()方法。测试读锁-读锁可以并发输出结果,从这里可以看到 Thread-0 锁定期间,Thread-1 的读操作不受影响测试读锁-写锁相互阻塞输出结果也是相互阻塞的,这里就不测试了。
2024-07-13 17:08:35
943
原创 7.3 ReentrantLock原理
先从构造器开始看,默认为非公平锁实现NonfairSync 继承自 AQS没有竞争时:第一个竞争出现时Thread-1 执行了当前线程进入 acquireQueued 逻辑再次有多个线程经历上述过程竞争失败,变成这个样子Thread-0 释放锁,进入 tryRelease 流程,如果成功当前队列不为 null,而且 head 的 waitStatus = -1,进入 unparkSuccessor 流程。
2024-07-13 17:05:00
790
原创 7.2 AQS原理
*** 自定义锁(不可重入锁)*/// 锁实现的大部分功能由该同步器类来实现// 独占锁@Override// state = 0 表示未加锁,state = 1 表示加锁// 加锁成功,并设置 Owner 为当前线程@Override// state 是 volatile 变量,可以保证指令不会重排序,应当放在最后,保证其他语句对其他线程可见// 是否持有独占锁@Override// 加锁,不成功会进入等待队列@Override// 加锁,可打断。
2024-07-13 17:04:23
1006
原创 7.1 线程池
线程池自定义线程池自定义拒绝策略接口@FunctionalInterfacepublic interface RejectPolicy<T> { void reject(BlockingQueue<T> queue, T task);}自定义任务队列@Slf4j(topic = "c.BlockingQueue")public class BlockingQueue <T> { // 任务队列 private Deque
2024-07-13 16:56:25
910
原创 (五)共享模型之无锁
Unsafe 对象提供了非常底层的,操作内存、线程的方法,Unsafe 对象不能直接调用,只能通过反射获得static {try {
2024-07-13 16:54:51
1162
原创 (三)共享模型之管程
线程安全问题案例两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?@Slf4j(topic = "c.ThreadSafe")public class ThreadSafe { public static int counter = 0; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(
2024-07-05 10:09:27
895
原创 (二)Java 线程
为什么需要 join?下面的代码执行,打印 r 是什么?test1();log . debug("开始");log . debug("开始");try {} log . debug("结束");r = 10;});log . debug("结果为:{}" , r);log . debug("结束");} }test1();log . debug("开始");log . debug("开始");try {} log . debug("结束");
2024-07-05 10:05:27
601
原创 (一)进程与线程
程序是有指令和代码组成的。进程是运行中的程序,进程可以视为程序的一个实例。一个进程之内可以分为一到多个线程。一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行。单核 CPU 下,线程实际还是 串行执行的。并行:多个 CPU 同时执行多个任务,比如:多个人同时做不同的事。并发:一个 CPU(采用时间片)同时执行多个任务,比如:秒杀、多个人做同一件事。一般会将这种线程轮流使用 CPU 的做法称为并发。
2024-07-05 10:04:30
374
原创 第十五章 垃圾回收相关算法
引用(指针) P指向了对象 A,A 中有一个属性又指向了对象 B,对象 B 中又有一个属性指向了对象 C,恰好对象 C 中又有一个属性指向了对象 A,即上图所示情况,对象 A、B、C 中的引用计数器分别为 2(分别是引用 P 和对象 C 中的属性),1,1。因此,基于老年代垃圾回收的特性,需要使用其他的算法。将活着的内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,最后完成垃圾回收。
2024-07-04 10:51:41
897
原创 第十四章 垃圾回收概述
现在,除了 Java 以外,C#,Python、Ruby 等语言都是用了自动垃圾回收的思想,也是未来发展趋势。可以说,这种自动化的内存分配和垃圾回收的方式已经成为现代开发语言必备的标准。
2024-07-04 10:51:07
310
原创 第十三章 StringTable
如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法:intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。比如:String myInfo = new String(“I love atguigu”).intern();也就是说,如果在任意字符上调用 String.intern 方法,那么其返回结果所指向的那个类实例,必须和直接以常量形式出现的字符串实例完全相同。
2024-07-04 10:50:37
496
原创 第十二章 执行引擎
解释器:当 Java 虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。JIT(Just In Time Compiler)编译器:就是虚拟机将源代码直接编译成和本地机器平台相关的机器语言。一般来讲,JIT 编译出来的机器码性能比解释器高C2 编译器启动时长比 C1 编译器慢,系统稳定执行以后,C2 编译器执行速度远远快于 C1 编译器。自 JDK 10 起,HotSpot 又加入一个全新的即时编译器:Graal 编译器。
2024-07-04 10:49:32
628
原创 第十一章 直接内存(Direct Memory)
读写文件,需要与磁盘交互,需要由用户态切换到内核态。在内核态时,需要内存如下图的操作。这里需要两份内存存储重复数据,效率低。使用 NIO 时,如下图。操作系统划出的直接缓存区可以被 Java 代码直接访问,只有一份。NIO 适合对大文件的读写操作。
2024-07-04 10:48:55
337
原创 第十章 对象的实例化内存布局与访问定位
它并不是一种具体的、固定不变的数据类型或实体,而是代表了程序设计中的一个广义的概念。句柄一般是指获取另一个对象的方法——一个广义的指针,它的具体形式可能是一个整数、一个对象或就是一个真实的指针,而它的目的就是建立起与被访问对象之间的唯一的联系。这两种对象访问方式各有优势,使用句柄来访问的最大好处就是 reference 中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为,如从 S0 区向 S1 区复制对象)时只会改变句柄中实例数据指针,而 reference 本身不需要修改。
2024-07-04 10:48:10
630
原创 第九章 方法区
Person 类的 .class 对应的运行时类本身要存放到方法区new 的 Person 对象需要放到堆空间中变量 person 需要放在 Java 虚拟机栈中《Java 虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于 HotSpot JVM 而言,方法区还有一个别名叫做 Non-Heap (非堆),目的就是要和堆分开。所以,方法区看作是一块独立于 Java 堆的内存空间。OOM 演示:测试结果:使用“-
2024-07-04 10:47:35
975
原创 第八章 堆
为新对象分配内存是一件非常严谨和复杂的任务,JVM 的设计者们不仅需要考虑内存如何分配、在哪里分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑 GC 执行完内存回收后是否会在内存空间中产生内存碎片。new 的对象先放伊甸园区。此区有大小限制。当伊甸园区的空间填满时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不在被其他对象所引用的对象进行销毁。再加载新的对象放到伊甸园区。然后将伊甸园区中的剩余对象移动到幸存者 0 区。
2024-07-04 10:47:00
951
原创 第七章 本地方法栈
Java 虚拟机栈用于管理 Java 方法的调用,而本地方法栈用于管理本地方法的调用。本地方法栈,也是线程私有的允许被实现成固定或者可动态扩展的内存大小。(在内存溢出方面是相同的)如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java 虚拟机将会抛出一个 StackOverflowError 异常。如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么 Java 虚拟机将会抛出一个 OutOfMemoryErr
2024-07-04 10:46:16
276
原创 第六章 本地方法接口
简单地讲,一个 Native Method 就是一个 Java 调用非 Java 代码的接口。一个 Native Method 是这样一个 Java 方法:该方法的实现由非 Java 语言实现,比如 C。这个特征并非 Java 所特有,很多其他的编程语言都有这一机制,比如在 C++ 中,你可以用 extern “C” 告知 C++ 编译器去调用一个 C 的函数。
2024-07-04 10:45:44
358
原创 第五章 虚拟机栈
参数表分配完毕之后,再根据方法体内定义的变量的顺序和作用域分配。我们知道类变量表有两次初始化的机会,第一次是在“准备阶段”,执行系统初始化,对类变量设置零值,另一次则是在“初始化”阶段,赋予程序员在代码中定义的初始值。和类变量初始化不同的是,局部变量表不存在系统初始化的过程,这意味着一旦定义了局部变量则必须人为的初始化,否则无法使用。
2024-07-04 10:45:08
871
原创 第四章 程序计数器(PC寄存器)
它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域。在 JVM 规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址;或者,如果是在执行 native 方法(本地方法,C/C++),则是未指定值(undefined)。它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
2024-07-04 10:44:28
2681
原创 第三章 运行时数据区概述及线程
内存是非常重要的系统资源,是硬盘和 CPU 的中间仓库及桥梁,承载着操作系统和应用程序的实时运行。JVM 内存布局规定了 Java 在运行过程中内存申请、分配、管理的策略,保证了 JVM 的高效稳定运行。不同的 JVM 对于内存的划分方式和管理机制存在着部分差异。Java 虚拟机定义了若干种程序运行期间会使用的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。
2024-07-04 10:43:23
316
原创 第二章 类加载子系统
在 Java 的日常应用程序开发中,类的加载几乎是由上述 3 中类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。隔离加载类修改类加载的方式扩展加载源防止源码泄露开发人员可以通过继承抽象类 java.lang.ClassLoader 类的方式,实现自己的类加载器,以满足一些特殊的需求。
2024-07-04 10:39:53
341
原创 第一章 JVM 与 Java 体系结构
Java 虚拟机是一台执行 Java 字节码的虚拟计算机,它拥有独立的运行机制,其运行的 Java 字节码也未必由 Java 语言编译而成。JVM 平台的各种语言可以共享 Java 虚拟机带来的跨平台性、优秀的垃圾回收器,以及可靠的即时编译器。Java 技术的核心就是 Java 虚拟机(JVM,Java Virtual Machine),因为所有的 Java 程序都运行在 Java 虚拟机内部。
2024-07-04 10:38:21
365
原创 SpringCloud Alibaba——分布式事务 Seata
本地事务,也就是传统的单机事务。在传统数据库事务中,必须要满足四个原则,即ACID:ACID,是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。原子性:事务中的所有操作,要么全部成功,要么全部失败。一致性:要保证数据库内部完整性约束、声明性约束。.................
2022-08-27 17:14:57
2070
1
原创 SpringCloud Alibaba-Sentinel 实现熔断与限流
在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了问题,调用这个服务救护出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的”雪崩效应“。雪崩发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方法响应变慢,亦或是某台机器的资源耗尽。..................
2022-08-16 00:02:27
1061
原创 SpringCloud Alibaba—Nacos 服务注册和配置中心
Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理的平台。它可以帮助我们轻松构建云原生应用程序和微服务平台。总结:Nacos 就是的组合,即。
2022-08-07 17:36:38
479
原创 SpringCloud Sleuth 分布式请求链路跟踪
SpringCloudSleuth主要功能就是在分布式系统中提供追踪的解决方案,并且兼容支持了Zipkin,只需要在pom文件中引入相应的依赖即可。Zipkin是Twitter的一个开源项目,它基于GoogleDapper实现,致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。Collector收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为Zipkin内部处理的Span格式,以支持后续的存储、分析、展示等功能。......
2022-07-31 22:41:50
1033
原创 SpringCloud Stream 消息驱动
SpringCloudStream由一个中间件中立的核组成。应用通过SpringCloudStream插入的input(相当于消费者consumer,它是从队列中接收消息的)和output(相当于生产者producer,它是从队列中发送消息的)通道与外界交流。通道通过指定中间件的Binder实现与外部代理连接。业务开发者不再关注具体消息中间件,只需要关注Binder对应用程序提供的抽象概念,通过这些抽象概念来使用消息中间件实现业务即可。https。.....................
2022-07-24 23:54:21
689
原创 SpringCloud Bus 消息总线
SpringCloudBus配合SpringCloudConfig使用,可以实现配置的动态刷新。SpringCloudBus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。SpringCloudBus目前支持RabbitMQ和Kafka。......
2022-07-24 19:04:59
187
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人