JUC
文章平均质量分 78
Java高并发
枫陵
这个作者很懒,什么都没留下…
展开
-
用户线程和守护线程(附代码示例)
概念Java线程分为守护线程和用户线程守护线程,是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程用户线程,是系统的工作线程,它会完成这个程序需要完成的业务操作当程序中所有用户线程执行完毕之后,不管守护线程是否结束,系统都会自动退出。如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以当系统只剩下守护线程的时候,Java虚拟机会自动退出代码示例开启一个线程a, 默认为用户线程,内部通过while循环使其无法结束。 当...原创 2022-04-25 16:59:08 · 350 阅读 · 0 评论 -
CompletableFuture的理解(附代码示例)
概念在Java8中,CompletableFuture提供 了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法。它可能代表一个明确完成的Future, 也有可能代表一个完成阶段( CompletionStage ),它支持在计算完成以后触发一些函数或执行某些动作。它实现了Future和CompletionStaqe接口。优点:1. 异步任务结束时,会自原创 2022-04-25 18:41:29 · 760 阅读 · 1 评论 -
volatile详解
一. volatile的内存语义当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内中当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,直接从主内存中读取共享变量所以volatile的写内存语义是直接刷新到主内存中,读的内存语义是直接从主内存中读取二.volatile变量的读写过程Java内存模型中定义的8种工作内存与主内存之间的原子操作:read(读取) -> l...原创 2022-04-29 12:53:40 · 11210 阅读 · 6 评论 -
线程中断机制,使用中断标识停止线程的的3种方法(附代码示例)
1. 什么是中断?1. 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。所以,Thread stop, Thread. suspend, Thread.resume都已经被废弃了。2. 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制————中断。3. 中断只是一种协作机制(并不能立刻stop一个线程),Java没有给中断增加任何语法,中断的过程完...原创 2022-04-26 10:46:32 · 1554 阅读 · 0 评论 -
LockSupport线程唤醒机制(附代码示例)
线程等待和唤醒的三种方法:方式1:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程方式2:使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程方式3:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程方式1与方式2:线程先要获得并持有锁,必须在锁块(synchronized或lock)中; 必须要先等待后唤醒,线程才能够被唤醒方式1:Object类中的wait, notify原创 2022-04-26 21:41:33 · 759 阅读 · 0 评论 -
Java内存模型(JMM)
一. JMM的定义JMM(Java内存模型 Java Memory Model,简称JMM)本身是一种抽象的概念并不真实存在它仅仅描述的是一组约定或规范,通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式并决定一个线程对共享变量的写入以及如何变成对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性和有序性展开的原则:JMM的关键技术点都是围绕多线程的原子性、可见性和有序性展开的作用:1 通过JMM来实现线程和主内存之间的抽象关系。...原创 2022-04-29 11:30:41 · 351 阅读 · 0 评论 -
FutureTask的理解(附代码示例)
FutureTask的概念Future接口定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。比如主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,过了一会才去获取子任务的执行结果。FutureTask的缺点get()容易导致阻塞:只要出现get方法,不管是否计算完成都阻塞等待结果出来再运行解决办法:用轮询(CAS)替代阻塞(但是轮询也...原创 2022-04-25 17:41:00 · 395 阅读 · 0 评论 -
Java锁——乐观锁与悲观锁
乐观锁概念乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的适用场景适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。 ...原创 2022-05-04 10:39:23 · 2685 阅读 · 2 评论 -
Java锁——从字节码分析synchronized及monitor
1. synchronized同步代码块m1方法代码 public void m1(){ synchronized (object){ System.out.println("----------hello sync"); } }m1方法字节码synchronized实现使用的是monitorenter和monitorexit指令一般情况下,monitorenter :monitorexit原创 2022-05-04 11:26:40 · 884 阅读 · 2 评论 -
Java锁——公平锁与非公平锁
概念公平锁:按序排队,判断同步队列是否还有先驱节点(hasQueuedPredecessors)的存在(我前面还有人吗?),如果没有先驱节点才能获取锁非公平锁: 先占先得,只要能抢获到同步状态就可以问题为什么会有公平锁和非公平锁的设计?为什么默认非公平?1. 恢复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU空闲状态时间2. 使用多线程很重要的考量点原创 2022-05-04 15:27:23 · 1247 阅读 · 0 评论 -
Synchronized锁升级:无锁-> 偏向锁 -> 轻量级锁 -> 重量级锁
一. 概述1. Synchronized锁升级的原因用锁能够实现数据的安全性,但是会带来性能下降。无锁能够基于线程并行提升程序性能,但是会带来安全性下降。2. Synchronized锁升级的过程无锁-> 偏向锁 -> 轻量级锁 -> 重量级锁3.早期synchronized效率低的原因 Java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会...原创 2022-05-07 18:33:00 · 2410 阅读 · 0 评论 -
Java锁——可重入锁(递归锁)
概念指在同一个线程外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提,锁对象得是同一个对象),不会因为之前已经获取过还没释放而阻塞。即一个线程中的多个流程可以获取同一把锁,持有这把同步锁可以再次进入可重入锁种类1. 隐式锁隐式锁(即synchronized关键字使用的锁)默认是可重入锁 。在一个synchronized修饰的方法或代码块的内部调用本类的其他synchronized修饰的方法或代码块时,是永远可以得到锁的代码示例 stati...原创 2022-05-04 15:44:27 · 1670 阅读 · 0 评论 -
Java强、软、弱、虚四大引用(附代码示例)
一. 整体架构Reference: 强引用SoftReference: 软引用WeakReference: 弱引用PhantomReference: 虚引用二. 强引用概念当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。在 Java中最常见的就是强引用,把一个对象赋给一个引用变...原创 2022-05-05 18:43:11 · 1083 阅读 · 0 评论 -
多线程条件下使用SimpleDateFormat报错:java.lang.NumberFormatException: multiple points、empty String、For input
错误详情 使用时间格式转换SimpleDateFormat方法的时候,用static修饰,并在处于多线程的情况下执行,结果出现各种报错信息 public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static Date parse(String stringDate) throws ParseException { retur...原创 2022-05-05 19:01:40 · 1195 阅读 · 0 评论 -
Java锁 —— CAS
一. 定义CAS(compare and swap)的缩写,译为比较并交换,实现并发算法时常用到的一种技术。它包含三个操作数——内存位置、预期原值及更新值。执行CAS操作的时候,将内存位置的值与预期原值比较:如果相匹配,那么处理器会自动将该位置值更新为新值;如果不匹配,处理器不做任何操作,多个线程同时执行CAS操作只有一个会成功。二. 原理CAS有3个操作数,位置内存值V,旧的预期值A,要修改的更新值B。当且仅当旧的预期值A和内存值V相同时,将内...原创 2022-05-04 17:54:55 · 2152 阅读 · 0 评论 -
Java锁——死锁及排查
概念死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去,如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。死锁产生主要原因1. 进程运行推进的顺序不合适2. 资源分配不当3. 系统资源不足代码示例线程a,b相互持有并期望,造成死锁public class DeadLockDemo { static Object lockA = n...原创 2022-05-04 15:56:34 · 307 阅读 · 0 评论 -
原子操作类——对象的属性修改原子类(以AtomiclntegerFieldUpdater为例)
对象的属性修改原子类的类型AtomiclntegerFieldUpdater ——原子更新对象中int类型字段的值AtomicL ongFieldUpdater ——原子更新对象中Long类型字段的值AtomicReferenceFieldUpdater ——原子更新引用类型字段的值使用目的以一种线程安全的方式操作非线程安全对象内的某一字段,可以不要锁定整个对象,减少锁定的范围,只关注长期、敏感性变化的某一个字段而不是整个对象,以达到精确加锁+节约内存的目的 (类似医生...原创 2022-05-04 18:22:17 · 440 阅读 · 0 评论 -
无锁->ReentrantLock->ReentrantReadWriteLock->StampedLock讲解
一. 概述锁的演变过程无锁->独占锁->读写锁->邮戳锁1. 无锁:多线程抢占,数据混乱,无序2. ReentrantLock、synchronized:有序,数据一致性,每次只能来一个线程,不管什么操作缺点:读操作效率低3. ReentrantReadWriteLock:读写互斥,读读可以共享,提升大面积的共享性能,同时多人读。缺点:1. 锁饥饿问题,写线程获得不到锁 2. 读的过程中,如果没有释放,写线程不可以获得...原创 2022-05-08 16:17:18 · 677 阅读 · 0 评论 -
原子操作增强类——LongAdder
一. 性能对比阿里开发手册推荐jdk8使用LongAdder替代AtomicLong示例代码 题目:热点商品点赞计算器,点赞数加加统计,不要求实时精确。50个线程,每个线程100W次,统计总点赞数 比较synchronized、AtomicInteger、AtomicLong、LongAdder、LongAccumulator五种计数性能class ClickNumber{ int number = 0; public s...原创 2022-05-04 19:31:04 · 5064 阅读 · 2 评论 -
AbstractQueuedSynchronizer——AQS
1. 定义AbstractQueuedSynchronizer简称为AQS ,字面意思是抽象的队列同步器。技术解释是用来构建锁或者其它同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量表示持有锁的状态。2. 为何称AQS为JUC体系的基石?与AQS相关的包括Semaphore信号量、CyelicBarier、ReentrantReadWriteLock、CountDownLatch、Re...原创 2022-05-08 10:48:10 · 482 阅读 · 0 评论 -
ThreadLocal详解
一. ThreadLocal简介定义ThreadLocal提供线程局部变量。这些变量与正常的变量不同,因为每一个线程在访问ThreadLocal实例的时候(通过其get或set方法)都有自己的,独立初始化的变量副本。ThreadLocal实例通常是类中的私有静态字段,使用它的目的是希望将状态(例如,用户ID或事务ID)与线程关联起来作用实现每一个线程都有自己专属的本地变量副本(自己用自己的变量不麻烦别人,不和其他人共享,人人有份,人各一份)。主要解决了让...原创 2022-05-05 18:08:05 · 1326 阅读 · 0 评论