
JUC学习
文章平均质量分 95
库里不会投三分
会持续更新Java初阶到进阶实战的知识
展开
-
第十六章Java多线程常见模式
图中 Futures 就好比居民楼一层的信箱(每个信箱有房间编号),左侧的 t0,t2,t4 就好比等待邮件的居民,右侧的 t1,t3,t5 就好比邮递员。来进行通讯,所以生产者生产完数据之后不用等 待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取.在 Java 标准库中内置了阻塞队列 . 如果我们需要在一些程序中使用阻塞队列 , 直接使用标准库中的即可 .阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力.阻塞队列也能使生产者和消费者之间 解耦.原创 2023-07-03 10:49:02 · 162 阅读 · 0 评论 -
第十五章Java并发集合
目录第一代线程安全集合类 HashTable与HashMap对比第二代线程非安全集合类第三代线程安全集合类 ConcurrentHashMap结构JDK1.7JDK1.8JDK8中的ConcurrentHashMap为什么使用synchronized来进行加锁?原创 2022-08-15 22:08:32 · 1277 阅读 · 0 评论 -
第十四章线程工具类
这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,知道最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法。release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。原创 2023-07-03 10:39:02 · 126 阅读 · 0 评论 -
第十二章线程池
我们的线程池中的线程就是对应的消费者,主线程是生产者,消费者从阻塞队列拿任务,主线程填入任务@FunctionalInterface // 拒绝策略 interface RejectPolicy < T > {什么是拒绝策略,如果当任务很多的时候,我们线程池处理不了,也就是我们的阻塞队列满了,这时候就需要对应的处理方法,这里的方法就是拒绝策略这里为什么要定义一个接口,我们知道不同的场景下需要不同的策略,如果我们写死在我们的阻塞队列,那么不符合开闭原则,也会有大量的if-else。原创 2023-07-03 10:37:04 · 651 阅读 · 0 评论 -
第十章Java对象布局
简单类对象的实例化过程1、在方法区加载类;2、在栈内存申请空间,声明变量P;3、在堆内存中开辟空间,分配对象地址;4、在对象空间中,对对象的属性进行默认初始化,类成员变量显示初始化;5、构造方法进栈,进行初始化;6、初始化完成后,将堆内存中的地址赋给引用变量,构造方法出栈;子类对象的实例化过程1、在方法区先加载父类,再加载子类;2、在栈中申请空间,声明变量P;3、在堆内存中开辟空间,分配对象地址;4、在对象空间中,对对象的属性(包括父类的属性)进行默认初始化;5、子类构造方法进栈;原创 2023-07-03 10:31:28 · 247 阅读 · 0 评论 -
第八章CAS策略
譬如AtomicInteger原子整型,可否有其他原子类型?比如AtomicBook、AtomicOrder*可以!丢入泛型中@Getter@ToStringint age;原创 2023-07-03 10:29:48 · 155 阅读 · 0 评论 -
第二章线程状态
线程之间可以互相sleep,互相yield。我们发现t2线程执行yield,让出CPU的使用权,t2线程只是让出CPU,但是下此调度什么线程,还是由我们的操作系统说的算,可能下次调用的还是t2线程(只不过是我们执行完输出这个语句,就把CPU让出去了),也有可能是t1线程,我们无法干涉,只是每次执行到t2线程,都会把CPU让出去,让t1线程执行的次数可能较多一点。,等待被调度选中,获得CPU的使用权,这种状态称为就绪态(万事俱备,只差CPU),当这个线程获得了CPU的使用权,那么就会从就绪态变为运行中。原创 2023-07-03 10:15:13 · 121 阅读 · 0 评论 -
第十一章详解synchronized锁升级
轻量级锁的获取轻量级锁是为了在线程近乎交替执行同步块时提高性能。主要目的:在没有多线程竞争的前提下,通过CAS减少重量级锁使用操作系统互斥量产生的性能消耗.说白了先自旋,不行才升级阻寨。升级时机:当关闭偏向锁功能或多线程竞争偏向锁会导致偏向锁升级为轻量级锁轻量级锁的加锁JVM会为每个线程在当前线程的栈帧中创建用于存储锁记录的空间,官方成为Displaced Mark Word。若一个线程获得锁时发现是轻量级锁,会把锁的MarkWord复制到自己的Displaced Mark Word里面。原创 2023-06-21 16:04:30 · 1596 阅读 · 0 评论 -
第九章ThreadLocal
从Java官方文档中的描述:ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get和set方法访问)时能保证各个线程的变量相对独立于其他线程内的变量(都有自己的、独立初始化的变量副本)。ThreadLocal实例通常来说都是类型的,用于关联线程和线程上下文,使用它的目的是希望将状态(例如,用户ID或事务ID)与线程关联起来。在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。原创 2023-06-18 15:25:30 · 362 阅读 · 0 评论 -
第七章volatile详解
其中最核心的操作是在于我们的write操作,当我们从工作内存写到主内存的时候,会进行lock加锁操作,加锁后会清空其他线程工作内存变量的值,如果其他线程要使用该变量前必须重写从主内存加载值,当write完毕后,进行unlock进行解锁 ,这样就保证了可见性。内存屏障(也称内存栅栏,内存栅障,屏障指令等,是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作),:处理器在读屏障之后的读操作, 都在读屏障之后执行。原创 2023-06-13 18:39:45 · 1108 阅读 · 0 评论 -
第六章JMM内存模型
Java中普通的共享变量不保证可见性,因为数据修改被写入内存的时机是不确定的,多线程并发下很可能出现"脏读",所以每个线程都有自己的工作内存,线程自己的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取,赋值等 )都必需在线程自己的工作内存中进行,而不能够直接读写主内存中的变量。根据上面的铺垫,我们Java也可以直接复用操作系统层面的内存模型。:对一个volatile变量的写操作先行发生于对这个变量的读操作,前面的写对后面的读是可见的,这里的后面同样是指时间上的先后。原创 2023-06-12 23:22:53 · 458 阅读 · 0 评论 -
第五章线程中断与等待唤醒机制
首先一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。其次在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的协商机制——中断。中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。原创 2023-06-12 23:21:43 · 376 阅读 · 0 评论 -
第四章Java锁—基础
指针指向monitor对象(也称为管程或监视器锁)的起始地址。每个对象都存在着一个monitor与之关联,当一个monitor被某个线程持有后,它便处于锁定状态。在Java虚拟机(HotSpot)中,monitor是由ObjectMonitor实现的,其主要数据结构如下(位于HotSpot虚拟机源码ObjectMonitor.hpp,C++实现的)原创 2023-06-12 23:19:17 · 651 阅读 · 0 评论 -
第三章Future与CompletableFuture
它实现了Future和Completion Stage接口阻塞的方式和异步编程的设计理念相违背,而轮询的方式会消耗无畏的CPU资源。因此,JDK8设计出CompletableFutureCompletableFuture提供一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。原创 2023-06-12 23:18:10 · 682 阅读 · 0 评论 -
第一章JUC概述
在 Java 5.0 提供了 java.util.concurrent ( 简称JUC ) 包, 在此包中增加了在并发编程中很常用的实用工具类, 用于定义类似于线程的自定义子系统, 包括线程池、 异步 IO 和轻量级任务框架。提供可调的、 灵活的线程池。还提供了设计用于多线程上下文中的 Collection 实现等涉及到的包内容。原创 2023-06-12 23:17:37 · 924 阅读 · 0 评论