返回顶部
首页 > 资讯 > 后端开发 > JAVA >JUC包(java.util.concurrent)下的常用子类
  • 907
分享到

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

javajvm面试java-ee 2023-09-14 14:09:38 907人浏览 安东尼
摘要

文章目录 前言一、对象锁juc.locks包二、原子类三、四个常用工具类3.1 信号量 Semaphore3.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在本篇就不多介绍,读者可以自行查阅一下官方文档进行仔细的学习~如果有问题可以私信博主,别忘了点赞收藏+关注哦!

来源地址:https://blog.csdn.net/qq_43575801/article/details/128057659

--结束END--

本文标题: JUC包(java.util.concurrent)下的常用子类

本文链接: https://lsjlt.com/news/407311.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JUC包(java.util.concurrent)下的常用子类
    文章目录 前言一、对象锁juc.locks包二、原子类三、四个常用工具类3.1 信号量 Semaphore3.2 CountDownLatch 总结 前言 博主个人社区:开发与算...
    99+
    2023-09-14
    java jvm 面试 java-ee
  • Java中JUC包(java.util.concurrent)下的常用子类
    目录一、对象锁juc.locks包二、原子类三、四个常用工具类3.1 信号量 Semaphore3.2 CountDownLatch总结一、对象锁juc.locks包 在Java中除...
    99+
    2022-12-20
    java util类 java.util包中的类 juc包有哪些常用的
  • 【JavaEE】JUC(Java.util.concurrent)常见类
    文章目录 前言ReentrantLock原子类线程池信号量CountDownLatch相关面试题 前言 经过前面文章的学习我们大致了解了如何实现多线程编程和解决多线程编程中遇到的线程不安...
    99+
    2023-10-10
    java java-ee 信号量 ReentrantLock 多线程 CountDownLatch
  • java多线程JUC常用辅助类详解
    1.countDownLatch 减法计数器:实现调用几次线程后,在触发另一个任务 简单代码实现: 举例说明:就像五个人在同一房间里,有一个看门的大爷,当五个人都出去后,他才能锁门...
    99+
    2024-04-02
  • java并发JUC工具包AtomicInteger原子整型语法的示例分析
    这篇文章主要介绍了java并发JUC工具包AtomicInteger原子整型语法的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。AtomicInteger 类底层存储...
    99+
    2023-06-29
  • Java JUC的核心类AQS有什么用
    这篇文章主要介绍“Java JUC的核心类AQS有什么用”,在日常操作中,相信很多人在Java JUC的核心类AQS有什么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java JUC的核心类AQS有什么用...
    99+
    2023-06-02
  • Java中常用的原子类有哪些
    小编给大家分享一下Java中常用的原子类有哪些,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、什么是原子类Java中提供了一些原子类,原子类包装了一个变量,并且提供了一系列对变量进行原子性操作的方法。我们在多线程环境下对...
    99+
    2023-06-15
  • wordpress调用当前分类下子分类的方法
    本文实例讲述了wordpress调用当前分类下子分类的方法。分享给大家供大家参考。具体分析如下: 自己没用过wordpress博客但是个人认为wordpress有函数可直接来子调用当前分类下的子分类的,但是我找了很久没找...
    99+
    2022-06-12
    wordpress 调用 当前 分类 子分类 方法
  • 详细总结Java中常用的原子类
    目录一、什么是原子类二、原子类的底层实现三、常用的原子类3.1 AtomicInteger与AtomicLong3.2 LongAdder四、原子类的性能测试4.1 测试程序4.2 ...
    99+
    2024-04-02
  • Spark RDD常用算子是什么类型的
    小编给大家分享一下Spark RDD常用算子是什么类型的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Spark RDD常用算子:Value类型Spark之所以比...
    99+
    2023-06-27
  • java并发包常用类有哪些
    常用的Java并发包中的类有:1. java.util.concurrent.Executor:用于管理和执行任务的接口。2. ja...
    99+
    2023-09-11
    java
  • java常用API介绍之包装类
    目录 前言一、包装类包装类有以下特点: 前言 在学习本课题之前,我们首先需要知道什么是API。 API,即Application Programming Inte...
    99+
    2023-05-16
    java常用API java包装类
  • java 如何扫描指定包下类(包括jar中的java类)
    在很多的实际场景中,我们需要得到某个包名下面所有的类, 包括我们自己在src里写的java类和一些第三方提供的jar包里的类,那么怎么来实现呢? 今天带大家来完成这件事。 src下面...
    99+
    2024-04-02
  • 常用的云服务器包括哪些类型
    公共云服务是指由第三方提供商提供的云计算服务,如亚马逊AWS、微软Azure和谷歌云平台等。这些云服务通常提供可扩展的计算资源和存储空间,可以帮助用户轻松地管理和扩展云资源。 私有云服务是指用户自己拥有服务器的云计算服务,如Amazon ...
    99+
    2023-10-28
    常用 类型 服务器
  • 使用java怎么扫描指定包下的类
    本篇文章给大家分享的是有关使用java怎么扫描指定包下的类,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java可以用来干什么Java主要应用于:1. web开发;2. And...
    99+
    2023-06-14
  • Python_子类调用父类的方法
    1.方式一子类调用父类的方法,包含2中形式的调用。一种形式是在类内部通过继承的方式调用父类的方法,另外一种形式是子类实例化后之后通过继承的方式来调用父类的方法。如下图所示:注意一点,在子类内部通过继承的方式调用父类的属性时,必须要带上sel...
    99+
    2023-01-31
    子类 方法
  • java同一个包下的类怎么互相调用
    在同一个包下的类可以直接互相调用,不需要使用任何关键字或语法来指明调用关系。只需在需要调用的方法前面加上类名即可。例如,假设有两个类...
    99+
    2023-08-20
    java
  • 常用JDBC数据库驱动包和类名
    陈九礼常用JDBC数据库驱动包和类名MySQL数据库: 1)驱动包:https://mvnrepository.com/artifact/mysql/mysql-connector-java(下载路径) 2)驱动类名:com...
    99+
    2022-03-15
    常用JDBC数据库驱动包和类名
  • 常用的云服务器包括哪些功能类型
    云服务器是一种基于云计算技术的虚拟服务器,它可以提供多种功能类型,以下是常用的几种: 1.计算型云服务器 计算型云服务器是一种专门用于处理计算密集型任务的云服务器,它通常配备高性能的 CPU 和大量的内存,可以快速处理大量的数据和复杂的计...
    99+
    2023-10-27
    常用 类型 功能
  • 常用的云服务器包括什么功能类型
    虚拟化技术是将物理硬件资源虚拟为逻辑资源,以此提高系统的可用性和性能。常用的虚拟化技术包括VMware、Hyper-V和Docker等。VMware是最流行的虚拟化技术之一,Hyper-V可以将多个物理服务器虚拟为多个逻辑服务器,以提高系统...
    99+
    2023-10-28
    常用 类型 功能
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作