JUC 包

juc包括:锁,线程池,原子类,并发集合,其他类。

1)锁

synchronized是jvm的关键字,ReentrantLock是通过JDK实现的。

为什么要使用锁?

为了防止在高并发的情况下导致数据不一致,所以需要保证在执行过程中原子性,有序性,可见性。

锁类型:乐观锁,悲观锁

乐观锁:就是俩个线程一直执行不会发生锁冲突,如果锁冲突,则重试直到成功。

乐观锁实现原理:采用cas机制,是通过sun包中unsafe类直接操作底层的操作系统中的内存空间,修改数据。

cas: 主存A,旧值B,修改值C 就是当获取B值与A相同的时候,将C值刷新到主存,否则什么都不做。

悲观锁:就是只能一个线程获取锁独占,线程获取锁之后只能它执行完毕之后,才会释放锁,其他锁才能去抢占。

synchronized-关键字

synchronized这个关键字实现原理:通过俩个原子操作命令moniterEnter和moniterExit命令,通过编译时候将这两个命令编译进去;这样保证数据原子性,有序性,可见性。

volatile-关键字

volatile只能保证数据可见性,有序性,所以使用的时候去修变量。

volatile是通过内存屏障实现可见性,通过happens-before实现有序性

ReentrantLock-接口

ReentrantReadWriteLock可以通过方法获取读锁和写锁,readLock()方法获取读锁,也称共享锁,读锁和读锁直接不互排斥,writeLock()方法获取写锁,写锁也称为排他锁,写锁和写锁相互排斥,多个线程可以同时进行读锁的操作,但是写锁只能单独一个线程去操作。

Synchronized和Lock对比

1)锁的释放

Synchronized 只能在代码执行完成释放,线程发生异常 jvm会让线程释放锁。

Lock 在finally中释放锁,不然容易造成死锁。

2)锁的状态

Synchronized 无法判断

Lock 可以通过 tryLock方法进行判断。

3)存在层次

Synchronized 关键字,jvm上

Lock 是个接口

4)锁的获取

Synchronized A线程获取 B线程等待,A等阻塞,B会一直等待。

Lock 有多个获取方式,可以不断尝试获取锁,线程可以不用一直等待。

2)线程池
为什么使用线程池?

1)使用线程池能够对线程进行统一分配,调优,监控。

2)降低资源消耗(线程创建不受限制,可以自动销毁)。

3)提高响应速度和可管理性。

线程池的管理:

把工作单位和执行机制分离开,工作单位包含Runnable和Callable,执行机制为Exceutor框架。

Exceutor类提供使用ThreadPoolExceutor的简单的ExceutorService实现。

ThreadPoolExecutor原理:

是由一个线程集合workerSet和一个阻塞队列workerQueue构成,当前用户想线程池提交一个任务,线程池会将任务放到workerQueue,workers中的线程会不断从workerQueue中获取任务然后执行,当workQueue没有任务的时候,worker会阻塞,知道队列中有任务了就取出来继续执行。

任务提交线程池的执行过程:

1.线程池首先看当前运行的线程数量时候少于核心线程数量,如果是,则创建一个线程惊喜执行任务,如果都在执行任务,则进入2

2.判断BlockingQueue是否已经满了,没有满,则进入BlockingQueue,如果满了,则进入3.

3.如果创建一个新的工作线程会使 当前运行线程数量 超过 最大线程数量,则交给RejectedExcetorHandler来执行任务

ThreadPoolExceutor线程池包含核心配置:

最大线程数量(MaxmumPoolSize):

核心线程数量(corePoolSize):

线程空闲存活时间(keepAliveTime):

存活时间单位(unit):线程空闲存活时间的单位

阻塞队列(workQueue):用来存放等待被执行的任务队列

ArrayBlockingQueue 基于数组结构的有界阻塞队列。

LinkedBlockingQueue 基于链表结构二阻塞队列。

prioryBlockingQueue:具有优先级的无界阻塞队列。

拒接策略(handler):当线程都在运行,阻塞队列也满,采取当前策略进行任务处理。

Abortpolicy:直接抛出异常,默认策略。

CallerRunsPolicy:用调用射所在的线程来执行任务。

DiscardOldPolicy 丢弃阻塞队列中最前的线程,并且执行当前任务。

DiscardPolicy:直接丢弃任务。

3)原子类

原子类可以线程安全使用,通过voletile关键字+cas实现的。

原子更新基础类型

AtomicBoolean 原子更新布尔类型

AtomicInterger 原子更新整型

AtomicLong 原子更新长整型

原子更新数组类型

AtomicIntergerArrary 原子更新整数数组

AtomicLongArrary 原子更新长整型数组

AtomicReferenceArray 原子更新引用类型数组

原子更新引用类型

AtomicIntegerFieldUpdater 原子更新整型字段

AtomicLongFieldUpdater 原子更新长整型字段

原子更新字段类型

AtomicReference 原子更新引用类型

4)并发集合

ConcurrentHashMap详解

ConcurrentHashMap1.7实现原理

通过segment+分段锁,sagment+数组+链表,ConcurrentHash对象中保存一个Sagement数组,初始默认16个 segment,每个sagment元素,它通过继承ReentrantLock俩进行加锁,每次加锁对象是一个samgment对象,保证sagment对象是线程安全的。

ConcurrentHashMap1.8实现原理

通过CAS机制+synchronized实现线程安全,采用数组+链表+红黑树实现。

链表转化为红黑树时机:链表长度大于8的时候,当链表长度为8的时候,哈希碰撞的概率也非常低,降到0.0000006。

当红黑树节点小于6的时候,就会转化链表,这个时候通过链表进行查询和删除效率会比红黑树快。

CopyOnWriteArrayList详解

实现原理:是基于拷贝,通过一个可重入锁,用来保证线程安全访问,一个Object类型的数组,当然,也使用反射机制和CAS来保证原子性的修改lock域。

使用限制

1.不能用于实时读的场景,拷贝数据,新增元素都需要时间,无法满足。

2.由于写操作需要进行拷贝数据,消耗内存,在数组的内容比较多的情况下,可能会导致full gc。

相关推荐
2501_915373887 分钟前
Java调用C++教程:JNI与JNA两种方式详解
java·开发语言·c++
代码的余温23 分钟前
Marshalling与Demarshalling深度解析
java·分布式·跨进程通信
好学且牛逼的马24 分钟前
#13 学习反馈
java·学习·ai编程
在下uptown37 分钟前
数据同步系统搭建方案
java·后端·架构
_extraordinary_37 分钟前
Java String的使用续 -- StringBuilder类和StringBuffer
java·开发语言
用户6118472654239 分钟前
《Java 实战:用 Spring Boot 快速构建一个 RESTful 接口服务》
java
程序员岳焱39 分钟前
11.Java I/O 流:文件读写与数据持久化
java·后端
~央千澈~1 小时前
评论功能开发全解析:从数据库设计到多语言实现-优雅草卓伊凡
java·前端·数据库
异常君1 小时前
Java 调用 Python:五种实用方法全面对比与实战案例
java·python
谷宇1 小时前
【Java基础-环境搭建-创建项目】IntelliJ IDEA创建Java项目的详细步骤
java