JUC包(java.util.concurrent)下的常用子类

news2025/2/27 22:52:58

文章目录

  • 前言
  • 一、对象锁juc.locks包
  • 二、原子类
  • 三、四个常用工具类
    • 3.1 信号量 Semaphore
    • 3.2 CountDownLatch
  • 总结


前言

博主个人社区:开发与算法学习社区

博主个人主页:Killing Vibe的博客

欢迎大家加入,一起交流学习~~

一、对象锁juc.locks包

在Java中除了synchronized关键字可以实现对象锁之外,java.util.concurrent中的Lock接口也可以实现对象锁。

在这里插入图片描述

介绍一下这个lock锁的简要实现:

  • JDK1.0就有的,需要JVM借助操作系统提供的mutex系统原语实现

  • JDK1.5之后,Java语言自己实现的互斥锁实现,不需要借助操作系统的monitor机制

注:使用Lock接口需要显式的进行加锁和解锁操作。

我们可以使用Lock接口的实现子类ReentrantLock来进行加锁解锁:

ReentrantLock 可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全.

ReentrantLock 的用法:

  1. lock(): 加锁,获取锁失败的线程进入阻塞状态,直到其他线程释放锁,再次竞争,死等。
  2. trylock(超时时间): 加锁, 获取锁失败的线程进入阻塞态,等待一段时间,时间过了若还未获取到锁恢复执行,放弃加锁,执行其他代码
  3. unlock(): 解锁

synchronized和lock的区别:

  1. synchronized 是Java的关键字, 由 JVM 实现,需要依赖操作系统提供的线程互斥原语(mutex),而Lock标准库的类和接口,其中一个最常用的子类( ReentrantLock ,可重入锁),由Java本身实现的,不需要依赖操作系统

  2. synchronized 隐式的加锁和解锁,lock需要显示进行加锁和解锁

  3. synchronized 在获取锁失败的线程时,死等;lock可以使用trylock等待一段时间之后自动放弃加锁,线程恢复执行在这里插入图片描述

  4. synchronized 是非公平锁, ReentrantLock 默认是非公平锁. 可以通过构造方法传入一个 true 开启公平锁模式. 在这里插入图片描述

  5. synchronized不支持读写锁,Lock子类ReentrantReadWriteLock支持读写锁。在这里插入图片描述

  6. 更强大的唤醒机制. synchronized 是通过 Object 的 wait / notify 实现等待-唤醒. 每次唤醒的是一个随机等待的线程.ReentrantLock搭配 Condition 类实现等待-唤醒, 可以更精确控制唤醒某个指定的线程

小结:

一般场景synchronized足够用了,需要用超时等待锁,公平锁,读写锁再考虑使用juc.lock

如何选择使用哪个锁?

  • 锁竞争不激烈的时候, 使用 synchronized, 效率更高, 自动释放更方便.
  • 锁竞争激烈的时候, 使用 ReentrantLock, 搭配 trylock 更灵活控制加锁的行为, 而不是死等.
  • 如果需要使用公平锁, 使用 ReentrantLock.

二、原子类

原子类内部用的是 CAS 实现,所以性能要比加锁实现 i++ 高很多。原子类有以下几个:

  • AtomicBoolean
  • AtomicInteger
  • AtomicIntegerArray
  • AtomicLong
  • AtomicReference
  • AtomicStampedReference

以 AtomicInteger 举例,常见方法有:

addAndGet(int delta);   i += delta;
decrementAndGet(); --i;
getAndDecrement(); i--;
incrementAndGet(); ++i;
getAndIncrement(); i++;

三、四个常用工具类

juc包下一共有四个常用工具类:

  1. 信号量 - Semaphore
  2. 计数器 - CountDownLatch
  3. 循环栅栏 - CyclicBarrier
  4. 两个线程之间的交换器 - Exchanger

3.1 信号量 Semaphore

信号量Semaphore就是一个计数器,表示当前可用资源的个数

关于信号量Semaphore有两个核心操作:

  • P - 申请资源操作
  • V - 释放资源操作

Semaphore 的PV加减操作都是原子性的,再多线程场景下可以直接使用

public static void main(String[] args) {
        // 在构造参数传入可用资源的个数
        // 可用资源为6个
        Semaphore semaphore = new Semaphore(6);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + "准备申请资源");
                    // P操作,每次申请两个资源
                    semaphore.acquire(2);
                    System.out.println(Thread.currentThread().getName() + "获取资源成功");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "释放资源");
                    // V操作,默认释放一个占有的资源
                    semaphore.release(2);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 20; i++) {
            Thread t = new Thread(runnable,String.valueOf(i + 1));
            t.start();
        }
    }

3.2 CountDownLatch

有点类似于大号的join方法

调用await方法的线程需要等待其他线程将计数器减为0才能继续恢复执行。

public static void main(String[] args) throws InterruptedException {
        // 等待线程需要等待的线程数,必须等这10个子线程全部执行完毕再恢复执行
        CountDownLatch latch = new CountDownLatch(10);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(new Random().nextInt(1000));
                    System.out.println(Thread.currentThread().getName() + "到达终点");
                    // 计数器 - 1
                    latch.countDown();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(runnable,"运动员" + i + 1);
            t.start();
        }
        // main线程就是裁判线程,需要等待所有运动员到底终点再恢复执行
        // 直到所有线程调用countdown方法将计数器减为0继续执行
        latch.await();
        System.out.println("比赛结束~最终获胜的是鹏哥,有请冠军给大家高歌一首~");
    }

总结

至于CyclicBarrier和Exchanger在本篇就不多介绍,读者可以自行查阅一下官方文档进行仔细的学习~如果有问题可以私信博主,别忘了点赞收藏+关注哦!

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

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

相关文章

单元测试入门篇

一、单元测试是什么&#xff1f; 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证。在测试金字塔模型中处于最底层&#xff1a; 整个金字塔模型代表着越上层的测试集成度越高&#xff0c;执行速度越慢&#xff0c;越下层…

2014-2020年国有大型商业银行和全国股份制商业银行绿色信贷数据

数据集名称&#xff1a;国有大型商业银行和全国股份制商业银行绿色信贷数据 时间范围&#xff1a;2014-2020年 数据来源&#xff1a;商业银行历年业绩报告和社会责任报告 相关说明&#xff1a;绿色金融是指为支持环境改善、应对气候变化和资源节约高效利用的经济活动&#x…

C语言练习之递归实现n的k次方

文章目录前言一、思路二、代码以及运行截图1.代码2.运行截图总结前言 使用C语言递归计算N的k次方 一、思路 求n的k次方的原理就是&#xff1a; n^k nn……*n&#xff08;k个n进行相乘&#xff09; 可以得到一个公式&#xff1a; f(k){1k0n∗f(k)k>0f(k) \left\{\begin{…

利用Redis来实现分布式锁

Redis命令 SET 命令有个 NX 参数可以实现「key不存在才插入」&#xff0c;可以用它来实现分布式锁&#xff1a; 如果 key 不存在&#xff0c;则显示插入成功&#xff0c;可以用来表示加锁成功&#xff1b;如果 key 存在&#xff0c;则会显示插入失败&#xff0c;可以用来表示…

PLC中ST编程的自定义功能块

右键单击——添加对线——程序组织单元 弹出对话框 修改名称&#xff0c;选择功能块&#xff1b; VAR_INPUT&#xff1a;输入变量&#xff1b;VAR_OUTPUT:输出变量&#xff1b;VAR&#xff1a;局部变量&#xff1b; 创建一个闪烁功能块&#xff0c;可输入亮和灭的时间&#xff…

基于SSM的高校共享单车管理系统【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86468380 主要使用技术 SpringSpringMVCMybatisEasyUIJqueryMysql 功能介绍 系统用户管理&#xff1a; 用户管理&#xff1a;可以添加、修改、删除、检索用户信息&#xff08;头像、用户账…

PSO粒子群算法微电网优化调度(微电网孤岛运行优化调度)matlab程序

PSO粒子群算法微电网优化调度&#xff08;微电网孤岛运行优化调度&#xff09;matlab程序 【含风电、光伏、微型燃机、储能蓄电池、燃料电池】 参考文献&#xff1a;基于改进粒子群算法的微电网优化调度 摘 要&#xff1a;当今全球普遍面临着能源危机和环境污染的加重&#xf…

全国工企专利匹配数据(1998-2014)

1、数据来源&#xff1a;国家统计局&#xff08;工业企业数据&#xff09;、专利数据来源于国家知识产权局。 2、时间跨度&#xff1a;1998-2014 3、区域范围&#xff1a;全国 4、指标说明&#xff1a; 包含以下指标&#xff1a; 公开&#xff08;公告&#xff09;日、申请…

基于SSM的毕业设计管理系统【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86469261 主要使用技术 SpringSpringMVCMybatisBootstrapJqueryMysql 功能介绍 本系统的用户可以分为三种&#xff1a;管理员、教师、学生。 管理员&#xff1a;导师管理、学生管理&#x…

【雷达通信】合成孔径雷达地面运动目标检测技术研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

第九章 持续集成CI:基于GitHub的Action回归验证

第九章 持续集成CI&#xff1a;基于GitHub的Action回归验证 持续集成可以认为是一种优秀的开发实践&#xff0c;它可以在代码变更的时候及时反映代码状态。持续集成需要服务器的支持&#xff0c;可以考虑通过 gitlib ci 或者 jenkins 自己搭建持续集成服务器&#xff0c;更好的…

基于SSM的地方文创特产在线商城【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86468623 主要使用技术 SpringSpringMVCMybatisBootstrapMysql 功能介绍 前台&#xff1a; 注册登录&#xff1a;普通用户可进行注册登录&#xff1b; 商品显示&#xff1a;游客可查看今日…

在CentOS 7.7 x86_64上为python 2.7.5安装pip的靠谱方法

我的虚拟机是CentOS 7.7 x86_64系统&#xff0c;对应的python默认版本是2.7.5&#xff0c;但是没有安装pip&#xff0c;不方便安装第三方模块。 我想为为它安装pip工具&#xff0c;发现现有的安装方法都行不通了&#xff0c;比如先安装easy_install&#xff0c;再通过easy_inst…

矩阵分解算法

文章目录0 前言1. 矩阵分解原理1.1 LFM公式推导LFM损失函数算法关键代码实现1.2 BiasSVD1.3 SVD参考0 前言 在协同过滤算法中 我们知道近邻协同过滤算法的显著缺点&#xff1a; 没有充分利用物品本身的属性信息处理稀疏矩阵能力很弱&#xff0c;泛化能力很弱 为了解决以上问…

Flink-窗口概念以及窗口API使用

6.3 窗口 6.3.1 窗口的概念 存储桶 水位线只是用来推动窗口的关闭&#xff0c;但不决定数据分到哪个窗口 6.3.2 窗口的分类 按照驱动类型分类 时间窗口计数窗口 按照窗口分配数据的规则分类 滚动窗口&#xff1a;参数为窗口的大小 滑动窗口&#xff1a;参数为窗口大小&am…

[CVPR2022] Debiased Learning from Naturally Imbalanced Pseudo-Labels

Debiased Learning from Naturally Imbalanced Pseudo-Labels 要点&#xff1a; 1、伪标签&#xff1a;由经过标记源数据训练的分类器&#xff0c;对未标记目标数据做出的置信预测&#xff0c;被广泛应用于使模型适应未标记数据&#xff0c;例如半监督学习 2、由于固有的数据…

bat批处理脚本大全

目录 1、echo 2、注释 3、常见cmd命令 4、参数与变量 5、for循环 6、函数 7、数组 在windows上编程或者制作一些小工具&#xff0c;少不了使用批处理脚本&#xff0c;而且在各种开发环境搭建中我们经常会看到批处理脚本。批处理脚本以cmd命令为基础&#xff0c;增加一些变量和参…

【学生毕业设计】基于web学生信息管理系统网站的设计与实现(13个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

【计算机毕业设计】50.课程设计管理系统

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 网络的广泛应用给生活带来了十分的便利。所以把课程设计管理与现在网络相结合&#xff0c;利用JSP技术建设课程设计管理系统&#xff0c;实现课程设计管理的信息化。则对于进一步提高课程设计管理发展&#x…

【图像分割】基于神经气体网络 (NGN)实现图像分割附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …