java并发工具包JUC(Java Util Concurrent)

1. 什么是JUC

1.1 JUC简介

  • JUC(Java Util Concurrent)是Java中的一个并发工具包,提供了一系列用于多线程编程的类和接口,旨在简化并发编程并提高其效率和可维护性。JUC库包含了许多强大的工具和机制,用于线程管理、同步和协调。

1.2 并发与并行

并发和并行的区别

并发就是多个线程交替执行,速度快的就好像是一起执行一样

并行就是多个线程同时执行  

1.3 进程和线程

1.3.1 进程

  • 指系统中正在运行的一个应用程序的一个实例

1.3.2 线程

  • 一个进程包含多个线程,系统分配处理器时间资源的基本单位,或者说进程内独立执行的一个单元执行流,是程序执行的最小单位

线程的状态

  • Java 中的线程可以处于多种状态,这些状态反映了线程在其生命周期中的不同阶段。以下是 Java 线程可能经历的状态:

  1. NEW(新建)

  • 线程对象已经创建,但尚未启动。

  • 线程还没有调用 start() 方法。

  1. RUNNABLE(可运行)

  • 线程已经启动,并且准备好运行(正在等待 CPU 时间片)。(就绪)

  • 线程可能正在执行(运行中)

  1. BLOCKED(阻塞)

  • 当线程试图获取一个已经由其他线程持有的锁时,它会被阻塞直到锁被释放。

  1. WAITING(等待)

  • 线程处于无限期等待状态,等待其他线程执行特定的动作。

  • 这种状态通常是由调用 Object.wait() 等方法引起的。

  1. TIMED_WAITING(限时等待)

  • 线程处于有限期等待状态,等待其他线程执行特定的动作或等待特定的时间间隔。

  • 这种状态通常是由调用 Thread.sleep(long millis)Object.wait(long timeout)等方法引起的。

  1. TERMINATED [ˈtɜːmɪneɪtɪd](终止)

  • 线程已经执行完毕或因异常而终止。

  • 线程已经完成了它的任务或被强制停止。

wait和sleep的区别

  1. 使用方式

  • wait() 方法属于 Object 类,

  • sleep() 方法属于 Thread 类,是一个静态方法,

  1. 对锁的影响

  • wait() 会释放锁

  • sleep() 不会释放锁,抱着锁睡。

  1. 如何唤醒

  • wait() 方法需要手动唤醒 notify()或notifyAll()

  • sleep() 自己到点了,会自己苏醒

2. java.util.concurrent.locks

2.1 Lock

  • 可中断的锁等待:lockInterruptibly()方法允许等待锁的线程响应中断,而不会像synchronized那样一直等待下去。

  • 尝试非阻塞的获取锁:tryLock()方法尝试获取锁,如果当前锁不可用,立即返回false,不会阻塞线程。

  • 超时获取锁:tryLock(long time, TimeUnit unit)在指定的时间内尝试获取锁,超时后返回false。

2.2 ReentrantLock

2.2.1 主要特点

  1. 可重入:线程可以多次获取同一个锁,而不会导致死锁。

  2. 非阻塞锁尝试:提供了 tryLock 方法,可以在没有立即获得锁时选择返回而不是阻塞。

  3. 锁的公平性和非公平性:可以控制锁的分配策略,决定是否按照请求顺序分配锁。

  4. 条件变量:提供了 Condition 对象,可以用来实现更复杂的同步行为。

2.2.2 公平性和非公平性

  • 构造函数ReentrantLock() 创建一个默认为非公平的锁实例。

  • 构造函数ReentrantLock(boolean fair) 创建一个锁实例,如果 fairtrue 则创建一个公平锁,否则创建一个非公平锁。

  • 公平锁保证锁的获取顺序遵循先进先出(FIFO)的原则,即线程按照请求锁的顺序来获取锁。这意味着一个线程一旦开始等待锁,它将按照其等待时间的先后顺序获得锁。

  • 非公平锁不保证锁的获取顺序,线程在尝试获取锁时可以直接尝试获取,而无需考虑是否有其他线程正在等待。如果获取失败,则线程会进入等待队列。

2.2.3 主要方法

  • lock():获取锁。如果锁已被其他线程持有,则当前线程将阻塞,直到锁可用。

  • tryLock():尝试获取锁。如果锁可用,则获取锁并立即返回 true;如果锁不可用,则立即返回 false

  • tryLock(long time, TimeUnit unit):尝试获取锁,在指定的时间内等待锁,如果在指定时间内未能获取到锁,则返回 false

  • unlock():释放锁。

  • newCondition():创建一个新的 Condition 对象,可以用于 更0\复杂的同步操作。

2.3 ReentrantReadWriteLock

主要特点

  1. 读-写分离:

  • 读锁(ReadLock: 允许多个线程同时获取读锁,只要没有写锁被持有。

  • 写锁(WriteLock: 如果某个线程持有了写锁,则不允许其他线程获取任何类型的锁(读锁或写锁)。

  1. 可重入性:

  • 一个已经持有某种锁的线程可以再次获取同一类型的锁而不会发生死锁。

  • 例如,如果一个线程已经获取了写锁,它可以再次请求写锁而不被阻塞。

  1. 公平性和非公平性:

  • ReentrantReadWriteLock 支持公平和非公平两种模式。

  • 公平模式下,锁的获取顺序遵循请求顺序。

  • 非公平模式下,锁可能优先于队列中的等待线程被授予给新请求。

2.4 Synchronized

  1. synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  • 修饰代码块,被修饰的代码块称为同步代码块,作用范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象

public void method() {synchronized (this) {// 同步代码块}
}

Java

  • 修饰方法,被修饰的方法称为同步方法,其作用范围是整个方法,作用对象是调用这个方法的对象

public synchronized void synchronizedMethod() {// 方法体
}

Plain Text

  • 对于同步实例方法和同步代码块,锁是当前对象 (this)。对于同步静态方法,锁是当前类的 Class 对象。

2.5 Lock和synchronized的区别

  1. 概念

  • Lock是接口

  • synchronized是关键字

  1. 使用方式

  • synchronized使用在方法或代码块上,会自己解锁

  • Lock需要自己上锁,自己解锁

  1. 锁的力度

  • synchronized不能把控

  • Lock可以把控

  1. 公平性

  • synchronized是非公平锁

  • Lock可以设置它的公平性(默认非公平)

3. java.util.concurrent.atomic

  • java.util.concurrent.atomic提供了原子变量类,这些类支持原子操作,即不可中断的操作。这些类主要用于多线程环境中的高效并发编程,可以避免使用锁带来的性能开销。

3.1 原子变量类

  1. AtomicInteger

  • 主要方法

  • get(): 获取当前值。

  • set(int newValue): 设置当前值。

  • incrementAndGet(): 原子地将当前值加 1 并返回结果。

  • decrementAndGet(): 原子地将当前值减 1 并返回结果。

  • addAndGet(int delta): 原子地将当前值加上指定值并返回结果。

  • getAndIncrement(): 原子地将当前值加 1 并返回原来的值。

  • getAndDecrement(): 原子地将当前值减 1 并返回原来的值。

  • getAndAdd(int delta): 原子地将当前值加上指定值并返回原来的值。

  • compareAndSet(int expect, int update): 如果当前值等于预期值,则原子地将当前值设置为更新值;否则返回 false。

  1. AtomicLong

  • AtomicLongAtomicInteger类似,但处理的是64位的长整型值。

  1. AtomicReference

  • AtomicReference提供了一个引用类型的原子类,它可以存储任何类型的对象。这个类非常有用,因为它可以用来创建复杂的原子数据结构,比如原子队列、栈等。

  1. AtomicBoolean

  • AtomicBoolean是一个布尔型的原子类,提供了线程安全的布尔值更新。

3.2 原子数组

  1. AtomicIntegerArray: 一个整型原子数组。

  2. AtomicLongArray: 一个长整型原子数组。

  3. AtomicReferenceArray<T>: 一个引用类型原子数组。

这些类提供了与原子变量相似的方法,但针对数组元素:

  • get(index): 返回指定索引处的值。

  • compareAndSet(index, expectedValue, newValue): 如果指定索引处的值等于预期值,则以原子方式将其设置为给定的新值。

  • getAndIncrement(index): 以原子方式将指定索引处的值加一并返回旧值。

  • getAndDecrement(index): 以原子方式将指定索引处的值减一并返回旧值。

  • getAndAdd(index, delta): 以原子方式将指定索引处的值加上给定的增量并返回旧值。

  • addAndGet(index, delta): 以原子方式将指定索引处的值加上给定的增量并返回新值

3.3 计数器(LongAdder)

  1. LongAdder 是 Java 8 引入的一个高性能的计数器类,它位于 java.util.concurrent.atomic 包中。LongAdder 主要用于需要频繁更新和读取大量数据的并发场景,它通过使用无锁技术以及基于分段的计数器来实现高性能的原子操作。

  2. 方法

  • add(long x): 原子性地增加指定的值。

  • increment(): 原子性地增加1。

  • decrement(): 原子性地减少1。

  • reset(): 重置计数器。

  • sum(): 获取当前的总和

  1. LongAdder性能比AtomicLong高

4. 辅助类

4.1 CountDownLatch

  • 它允许一个或多个线程等待其他线程完成某些操作。CountDownLatch 类似于一个倒计时计数器,当计数器的值减至零时,所有等待的线程将被释放继续执行。

  • 主要方法

  1. 构造函数CountDownLatch(int count) 创建一个带有指定计数的 CountDownLatch 实例。

  2. countDown():每次调用此方法都会使计数减一。

  3. await():阻塞当前线程,直到计数变为零或超时。

  • await():等待计数变为零。

  • await(long timeout, TimeUnit unit):等待计数变为零,或者达到指定的超时时间。

4.2 CyclicBarrier

  • CyclicBarrier是Java中的一个同步辅助类,它可以让多个线程互相等待,直到所有线程都到达屏障点后才继续执行。需要传入一个整数作为参与线程的数量,当每个线程调用await()方法时,它们都会被阻塞,直到所有线程都调用了await()方法后才会一起继续执行

  • 主要方法

  1. 构造方法

  • CyclicBarrier(int parties): 创建一个新的 CyclicBarrier,参数 parties 指的是需要等待的线程数量。

  • CyclicBarrier(int parties, Runnable barrierAction): 与第一个构造函数类似,但当所有线程都到达屏障时,会有一个额外的 Runnable 任务被执行

  1. 成员方法

  • await():阻塞当前线程,直到所有参与的线程都调用了此方法。

  • reset(): 重置屏障,取消所有正在等待的线程。

  • getParties(): 返回屏障的参与者数量。

  • isBroken(): 返回一个布尔值表示屏障是否已被中断或超时。

4.3 Semaphore

  • 信号量,用于控制同时访问某个资源的线程数量。它的本质是一个“共享锁“。信号量维护了一个信号量许可集。线程可以通过调用 acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可

  • 主要方法

  1. 构造函数

  • Semaphore(int permits):创建一个具有给定数量许可的 Semaphore

  • Semaphore(int permits, boolean fair):创建一个具有给定数量许可的 Semaphore,并且可以选择是否公平分配许可。

  1. 获取许可

  • acquire():等待直到获取一个许可,如果所有许可都被占用,则线程将被阻塞。

  • acquireUninterruptibly():等待直到获取一个许可,即使线程被中断也不会抛出异常。

  • tryAcquire():尝试获取一个许可,如果许可可用则立即返回 true,否则返回 false

  • tryAcquire(long timeout, TimeUnit unit):尝试在给定时间内获取一个许可,如果在超时时间内许可可用则立即返回 true,否则返回 false

  1. 释放许可

  • release():释放一个许可,增加可用的许可数量。

  1. 查询状态

  • availablePermits():返回当前可用的许可数量。

  • getQueueLength():返回等待获取许可的线程数量。

  • hasQueuedThreads():返回是否有线程正在等待获取许可。

  • drainPermits():获取并消耗所有可用的许可。

public class SemaphoreDemo {public static void main(String[] args) {Semaphore semaphore = new Semaphore(3);
​
​for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {try {semaphore.acquire();System.out.println(Thread.currentThread().getName() + "running...");sleep(1000);System.out.println(Thread.currentThread().getName() + "end");} catch (InterruptedException e) {throw new RuntimeException(e);} finally {semaphore.release();}}, "线程" + i);thread.start();}}
}

Java

  • 示例代码中创建一个许可量为3的信号量,使用for循环创建10个线程去模拟请求信号量限制的资源,运行代码就会发现,某一时刻最多只有3个线程能访问。

4.4 CountDownLatch,CyclicBarrier,Semaphore的区别

  • CountDownLatch、CyclicBarrier、Semaphore都是Java并发库中的同步辅助类,它们都可以用来协调多个线程之间的执行

  1. CountDownLatch是一个计数器,它允许一个或多个线程等待其他线程完成操作。它通常用来实现一个线程等待其他多个线程完成操作之后再继续执行的操作。

  2. CyclicBarrier是一个同步屏障,它允许多个线程相互等待,直到到达某个公共屏障点,才能继续执行。它通常用来实现多个线程在同一个屏障处等待,然后再一起继续执行的操作。

  3. Semaphore是一个计数信号量,它允许多个线程同时访问共享资源,并通过计数器来控制访问数量。它通常用来实现一个线程需要等待获取一个许可证才能访问共享资源,或者需要释放一个许可证才能完成操作的操作。

  • CountDownLatch适用于一个线程等待多个线程完成操作的情况

  • CyclicBarrier适用于多个线程在同一个屏障处等待

  • Semaphore适用于一个线程需要等待获取许可证才能访问共享

5. ConcurrentHashMap

  • ConcurrentHashMap是Java中一个线程安全的HashMap实现,它被设计用于在多线程环境中高效地存储键值对。ConcurrentHashMap首次出现在Java 5(JDK 1.5)中,并且在Java 8中进行了重大的改进。

  • 在Java 5中,ConcurrentHashMap使用了分段锁(Segmented Locking)的策略来提高并发性能。Java 8中的ConcurrentHashMap放弃了分段锁的策略,转而采用了更简单的CAS(Compare and Swap)+ synchronized的组合方式。这样做的目的是降低锁竞争,并简化实现。

  • 在ConcurrentHashMap中,key和value都不允许为null

主要方法

  • get(key):获取键对应的值。

  • remove(key):删除指定键的映射。

  • containsKey(key):检查是否存在指定的键。

  • forEach(BiConsumer):遍历所有键值对。

  • computeIfAbsent(key, mappingFunction):如果键不存在,则计算并放入新值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149821.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Python报错已解决】NameError: name ‘reload‘ is not defined

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

【JVM】JVM执行流程和内存区域划分

是什么 Java 虚拟机 JDK&#xff0c;Java 开发工具包JRE&#xff0c;Java 运行时环境JVM&#xff0c;Java 虚拟机 JVM 就是 Java 虚拟机&#xff0c;解释执行 Java 字节码 JVM 执行流程 编程语言可以分为&#xff1a; 编译型语言&#xff1a;先将高级语言转换成二进制的机器…

飞腾平台perf工具PMU事件集成指南

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

linux信号| 学习信号三步走 | 学习信号需要打通哪些知识脉络?

前言: 本节内容主要讲解linux下信号的预备知识以及信号的概念&#xff0c; 信号部分我们将会分为几个阶段进行讲解&#xff1a;信号的概念&#xff0c; 信号的产生&#xff0c; 信号的保存。本节主要讲解信号 ps:本节内容适合学习了进程相关概念的友友们进行观看哦 目录 什么是…

大模型算法岗常见面试题100道(值得收藏)

大模型应该是目前当之无愧的最有影响力的AI技术&#xff0c;它正在革新各个行业&#xff0c;包括自然语言处理、机器翻译、内容创作和客户服务等等&#xff0c;正在成为未来商业环境的重要组成部分。 截至目前大模型已经超过200个&#xff0c;在大模型纵横的时代&#xff0c;不…

测试从业者需要了解心理学和经济学

对于测试从业者来说&#xff0c;测试工作是一项技术活&#xff0c;但同时它也涉及到经济学和人类心理学一些重要因素。 在理想情况下&#xff0c;我们会测试程序的所有可能执行情况&#xff0c;而在大多数情况下&#xff0c;这几乎是不可能的。即使一个看起来非常简单的程序&a…

828华为云征文|使用华为云Flexus云服务器X搭建部署茶叶商城小程序uniapp

在当今数字化时代&#xff0c;小程序以其便捷、高效的特点成为了众多商家拓展业务的重要渠道。 本文将详细介绍如何使用新购买的华为云 Flexus 云服务器 X 搭建&#xff0c;一个带商品采集功能、H5积分商城、集合拼团、砍价、秒杀、会员、分销等等功能一个茶叶商城小程序。 后端…

共享wifi公司哪家正规合法?具体流程全公开!

随着共享经济时代的到来&#xff0c;以共享wifi为代表的多个项目逐渐成为众多创业赛道中的一大热门&#xff0c;推出共享wifi及其他项目的公司数量也因此呈现出了快速增长的态势。而这也让共享wifi等市场出现了鱼龙混杂的情况&#xff0c;连带着共享wifi哪家公司正规合法等相关…

写作高质量文案很难,文案自动生成器轻松解决

在当今信息爆炸的网络环境中&#xff0c;拥有一篇高质量的文案对于吸引受众、传达信息和实现目标至关重要。然而&#xff0c;写作高质量文案并非易事&#xff0c;它需要作者具备深厚的语言功底、创新的思维以及对目标受众的精准把握。这一系列的要求常常让许多人陷入写作的困境…

Windows电脑使用VNC远程桌面本地局域网内无公网IP树莓派5

目录 前言 1. 使用 Raspberry Pi Imager 安装 Raspberry Pi OS 2. Windows安装VNC远程树莓派 3. 使用VNC Viewer公网远程访问树莓派 3.1 安装Cpolar步骤 3.2 配置固定的公网地址 3.3 VNC远程连接测试 4. 固定远程连接公网地址 4.1 固定TCP地址测试 作者简介&#xff1…

drools规则引擎

1 单个文件 这个大多搜索导的都是把规则放到一个文件&#xff0c;这个是基础&#xff0c;但是实际应用就不太方便。如果你使用的jdk1.8&#xff0c;那么对应的drools版本为7.x 1.1 pom依赖 <drools.version>7.74.1.Final</drools.version> <dependency>&…

KITTI数据集雷达采样点时间戳属性的思考(Failed to find match for field ‘time‘)

最近在SLAM调研期间&#xff0c;看到了FAST-LIO2以及Point-lio这两个比较新的SLAM建图算法&#xff0c;想着上手编译并且运行一下&#xff0c;选择了自己了解到的比较出名的数据集KITTI&#xff0c;想着在上述两个开源算法上上手跑一下&#xff08;原论文并没有使用KITTI数据集…

大功率400mw蓝光可调激光模组价格多少钱

在现代激光技术的快速发展中&#xff0c;大功率400mw蓝光可调激光模组以其卓越的性能和广泛的应用领域&#xff0c;成为了市场上备受瞩目的产品。那么&#xff0c;这款激光模组的价格究竟是多少呢? 大功率400mw蓝光可调激光模组的价格因品牌、规格、销售渠道及促销活动等因素而…

【Python报错已解决】TypeError: forward() got an unexpected keyword argument ‘labels‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

【机器学习】决策树算法

目录 算法引入 基尼系数&#xff1a; 决策树算法概述 决策树的关键概念 决策树的构建 代码实现 1. 定义决策树节点 2. 计算信息增益 3. 选择最佳分割特征 4. 构建决策树 5. 决策树预测 决策树的评估指标&#xff1a; 决策树的优缺点 优点&#xff1a; 缺点&…

Github优质项目推荐-第一期

文章目录 Github优质项目推荐一、【free-for-dev】&#xff0c;88.4k stars二、【linux-command】&#xff0c;31.5k stars三、【system-design-primer】&#xff0c;270k stars四、【GitHub-Chinese-Top-Charts】&#xff0c;99.1k stars五、【Docker-OSX】&#xff0c;46k st…

汇智生物---农业与植物基因组分析专家

1.博导团队免费指导设计 2.博导团队免费解读实验结果 3.实验整体!打包服务 4.实验整体!打包服务 表观组 互作组 DNA亲和纯化测序 DNA亲和纯化测序技术通过体外表达转录因子鉴定转录因子结合位点&#xff0c;不受抗体和物种限制&#xff0c;且具有高通量的优势。DAP-Seq将蛋…

鸿萌数据恢复:NAND 内存协议,SDR 与 DDR 之间的区别

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据恢复、数据备份解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 从事 NAND 数据恢复的人都知道&#xff0c;读取 NAND 需要使…

不可错过的10款文件加密软件,2024最新文件加密软件排行榜

在数字化时代&#xff0c;数据安全变得尤为重要。无论是个人用户还是企业组织&#xff0c;保护敏感文件和数据免受未经授权的访问是至关重要的。文件加密软件通过将文件内容转换为不可读的格式&#xff0c;确保只有授权用户才能解密和访问数据。本文将为您介绍2024年不可错过的…

828华为云征文 | 在华为云上通过Docker容器部署Elasticsearch并进行性能评测

目录 前言 1. 华为云X实例介绍及优势 1.1 柔性算力 1.2 vCPU和内存的灵活配比 1.3 成本效益与性能 2. 安装并运行 Docker 2.1 修改仓库配置文件 2.2 安装 Docker 2.3 启动 Docker 3. 使用Docker部署Elasticsearch 3.1 拉取Elasticsearch镜像 3.2 启动Elasticsearch…