Java并发包中那些值得学习的并发工具类(空谈误国,实干兴邦,代码示范,抛砖引玉)

2023-11-12

首先我们通常说的并发包就是java.util.concurrent包及其子包。集中了Java并发的各种基础工具类。

一、这个并发包在哪

在这里插入图片描述

上面的包就是传说中的并发包。
为什么这个并发包就比较流弊呢?
原因主要有以下几点。

  1. 提供了几个比synchronized更加高级的各种同步结构。例如:CountDownLatch、CyclicBarrier、Semaphore等。可以实现更加丰富的多线程的操作。比如利用Semaphore作为资源控制器(其实可以简单理解为信号量),限制同时工作的线程的数量。
    在这里插入图片描述

  2. 各种线程安全的容器。例如:无序的ConcurrentHashMap、有序的ConcurrentSkipListMap和线程安全的动态数组CopyOnWriteArrayList等。

在这里插入图片描述

  1. 各种并发队列的实现。比较典型的有ArrayBlockingQueue、SynchorousQueue或者优先级队列PriorityBlockingQueue等。

  2. 强大的Executor框架,可以创建各种不同类型的线程池,调度任务的运行,绝大部分情况下,用户不需要自己从头实现线程池和调度任务。

在这里插入图片描述

二、讲几个比较流弊用的较多的

万变不离其宗,抛砖引玉,如果这几个基础的你了解的比较好,以后再深入拓展就比较简单了。

空谈误国,实干兴邦,谢谢看嘛。

1、Semaphore

简单说,他就是一个计数器,其基本逻辑基于acquire/release申请或者获得资源。

  • Semaphore:Java版本的信号量的实现。用这个你就能实现对资源的管理。例如你一辆车做五个人,那么就赋值5。你只有一台打印机可以用,那就是1。

  • 1

package com.newframe.controllers.api;

import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.Semaphore;

/**
 * 第一步
 * 创建一个实现了Runnable接口的信号量工作类
 * 并重写它的run方法,让他做我想要做的事情
 */

public class SemaphoreWorker implements Runnable{

    private String name;

    private Semaphore semaphore;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //创建一个构造函数
    public SemaphoreWorker(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {

        try {
            log("准备申请一个资源");
            semaphore.acquire();//申请资源
            log("申请到了资源");
            log("执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放资源
            semaphore.release();
            log("释放资源成功");
        }

    }

    private void log(String msg){
        if (StringUtils.isEmpty(msg)){
            name = Thread.currentThread().getName();
        }

        System.out.println(name + " " + msg);
    }
}

  • 2
package com.newframe.controllers.api;

import java.util.concurrent.Semaphore;

/**
 * 第二步
 * 创建一个Semaphore的测试类
 */
public class TestSemaphore {

    public static void main(String[] args) {

        System.out.println("我要开始执行了");

        //创建一个Semaphore对象,允许3个资源
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 10; i++) {
            SemaphoreWorker worker = new SemaphoreWorker(semaphore);
            //给线程一个名字
            worker.setName("线程"+i);
            Thread thread = new Thread(worker);
            thread.start();
        }
    }
}

在上面可以很清晰的看到Semaphore对资源信号量的控制。
如我上面的信号量给的3,就是最多只能有3个线程能同时申请到资源。其余线程需要等待申请到的线程释放资源后才能获得资源。
看输出结果:

在这里插入图片描述

2、CountDownLatch和CyclicBarrier

他们的行为有一定的相似度。经常会用来要你理解他们有什么区别。

  • CountDownLatch 控制的这个数量是不可以重置的,两个线程不能够同时抢占CountDownLatch控制的资源数量。在前面的线程执行完后,后面的线程才可以执行。
  • CycliBarrier这个就很有意思了。这个比如说你有5个士力架,你上学,你吃完了,你一定要把5个都吃完,你立马可以获得新的5个士力架。你怕不怕。

3、CountDownLatch

下面我们来举个例子

  • 1
package com.newframe.controllers.api;

import java.util.concurrent.CountDownLatch;

/**
 * 创建第一个吃巧克力的家伙,叫他小明吧
 * 实现Runnable接口,并重写其方法
 */
public class FirstBatchWorker implements Runnable{

    private CountDownLatch latch;

    public FirstBatchWorker(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        //执行countDown()操作
        latch.countDown();
        System.out.println("小明吃了一块巧克力");
    }
}
  • 2
package com.newframe.controllers.api;

import java.util.concurrent.CountDownLatch;

/**
 * 创建第二个吃巧克力的家伙,叫他小李吧
 * 实现Runnable接口,并重写其方法
 */
public class SecondBatchWorker implements Runnable{

    private CountDownLatch latch;

    public SecondBatchWorker(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {

        try {
            latch.await();
            System.out.println("小李吃了一块巧克力");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  • 3
package com.newframe.controllers.api;

import java.util.concurrent.CountDownLatch;

/**
 * 来测试一下LatchSample
 */
public class TestCountDownLatch {

    public static void main(String[] args) {

        //一共5个巧克力
        //同时有5个线程可以获取到资源
        CountDownLatch latch = new CountDownLatch(5);

		//下面的线程是按照顺序执行的。
        //五个小明线程
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new FirstBatchWorker(latch));
            thread.start();
        }

        //这个线程一定要等到上个线程全部执行完成了才可以执行
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new SecondBatchWorker(latch));
            thread.start();
        }
    }
}

执行结果

小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小明吃了一块巧克力
小李吃了一块巧克力
小李吃了一块巧克力
小李吃了一块巧克力
小李吃了一块巧克力
小李吃了一块巧克力

CountDownLatch用于线程间等待操作结束是非常普遍简单的用法。

4、CyclicBarrier

如果说CountDownLatch 是用于线程间等待操作结束的协调,那么CyclicBarrier其实反映的是线程间并行运行时的协调。
下面来看一个例子。

  • 1、
package com.newframe.controllers.api;


import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 创建一个CyclicBarrier类,实现Runable接口
 */
public class CyclicBarrierWorker implements Runnable{

    private CyclicBarrier cyclicBarrier;

    public CyclicBarrierWorker(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {

        try {
            for (int i = 0; i < 3; i++) {
                System.out.println("执行");
                cyclicBarrier.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

  • 2、
package com.newframe.controllers.api;

import java.util.concurrent.CyclicBarrier;

/**
 * 测试一下CyclicBarrier
 */
public class TestCyclicBarrier {

    public static void main(String[] args) {

        CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("操作再次......执行");
            }
        });

        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new CyclicBarrierWorker(barrier));
            thread.start();
        }
    }
}

  • 执行结果
执行
执行
执行
执行
执行
操作再次......执行
执行
执行
执行
执行
执行
操作再次......执行
执行
执行
执行
执行
执行
操作再次......执行

三、Java并发库的小知识

Java并发库还提供了Phaser,功能与CountDownLatch很接近。
Java并发库还提供了线程安全的Map、List和Set等容器。

在这里插入图片描述

ConcurrentHashMap:侧重通过键值对,放入或者获取的速度,对顺序无所谓。
ConcurrentSkipListMap:通过键值对操作数据,侧重数据的顺序操作。如果对大量数据进行频繁的修改,ConcurrentSkipListMap也是有优势的。

好啦,今天就到这里啦。好记性比不上烂笔头,还是的亲自实践一下的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java并发包中那些值得学习的并发工具类(空谈误国,实干兴邦,代码示范,抛砖引玉) 的相关文章

  • ConcurrentHashMap、synchronized与线程安全

    最近做的项目中遇到一个问题 xff1a 明明用了ConcurrentHashMap xff0c 可是始终线程不安全 除去项目中的业务逻辑 xff0c 简化后的代码如下 xff1a public class Test40 public sta
  • ConcurrentHashMap解析

    https www cnblogs com ITtangtang p 3948786 html java util concurrent xff08 j u c xff09 源码阅读
  • 冒泡排序详解

    一 冒泡排序简介 常用排序算法 冒泡排序 Bubble Sort 是一种常见的排序算法 相对来说比较简单 冒泡排序重复地走访需要排序的元素列表 依次比较两个相邻的元素 如果顺序 如从大到小或从小到大 错误就交换它们的位置 重复地进行直到没有
  • ConcurrentHashMap详解

    目录 ConcurrentHashMap介绍 ConcurrentHashMap底层数据结构 ConcurrentHashMap部分分析 ConcurrentHashMap与HashMap HashTable的区别 源码为jdk1 7 Co
  • 前端异步编程的进化之旅 promise generator aysnc/await

    promise generator aysnc await 1 三者都是异步编程的解决方案 不同的是 promise为较早出来的 其次generator 最后为async await 三者象征了前端进行解决异步编程的进化路程 promise
  • Java知识点梳理:Collection框架

    java集合类是开发中经常用到的 比如ArrayList HashMap HashSet等 下面来系统的说一下 Collection类图 Collections与Collection Collection 是一个集合接口 提供了对集合对象进
  • 线程基础---基础方法

    线程启动 在Thread类中注释标明有两种方式创建新的执行线程 一种是声明一个类是Thread的子类 这个子类应该重写类Thread的run方法 然后可以分配和启动子类的实例 创建线程的另一种方法是声明一个实现Runnable接口的类 这个
  • Java 并发:“级联”变量中的 Volatile 与 Final?

    is final Map
  • JDK8中ConcurrentHashmap代码解释

    我一直在尝试理解 JDK8 中的 ConcurrentHashMap 函数 与 JDK7 中的函数相反 除了源代码之外 还可以找到一些好人 例如 Richard 对其进行了很好的解释http www burnison ca articles
  • 统计catch块中发生的异常数量

    我正在尝试收集发生异常的所有计数以及异常的名称ConcurrentHashMap这样我就应该知道这个异常发生了多少次 因此 在我的 catch 块中 我有一个映射 它将继续添加异常的名称和出现的总计数 下面是我的代码which I have
  • 递归 ConcurrentHashMap.computeIfAbsent() 调用永远不会终止。错误还是“功能”?

    前一段时间 我在博客中介绍了一种递归计算斐波那契数的 Java 8 函数方法 有一个ConcurrentHashMap缓存和新的 有用的computeIfAbsent method import java util Map import j
  • 并发 hashmap 不需要同步 getter/setter 吗?

    如果我使用并发哈希图并且我有设置和获取值的方法 因为我使用并发哈希图 我需要使 getter 和 setter 同步吗 这是多余的吗 有一种设计更好吗 另外 没有同步的并发哈希图是否比具有同步 getter 和 setter 的哈希图更快
  • 将对象重新放入 ConcurrentHashMap 是否会导致“发生在”内存关系?

    我正在与existing具有 ConcurrentHashMap 形式的对象存储的代码 映射内存储了可供多个线程使用的可变对象 根据设计 没有两个线程会尝试同时修改一个对象 我关心的是线程之间修改的可见性 目前 对象的代码在 setter
  • 固定大小的并发Map

    我需要一张满足以下要求的地图 应该是高并发的 这put get and remove 方法可以由多个线程同时调用 它应该是固定大小的 如果尺寸HashMap达到最大值 例如 10000 则不允许向映射添加新条目 它不能是 LRU 缓存 其中
  • Java ConcurrentHashMap 中增加分区数量的缺点?

    Java ConcurrentHashMap 在内部维护分区 每个分区可以单独加锁 在某些情况下 多个线程访问的所有键都落入同一分区 而分区可能没有帮助 进一步增加分区数量应该会提高并发性 为什么 Java 为分区计数提供默认值 16 而不
  • 使用 ConcurrentHashMap 可以消除数据可见性问题吗?

    我已读完Java 并发实践 http www javaconcurrencyinpractice com 剩下的问题是 当我使用 ConcurrentHashMap 时 我还需要担心本书第一部分中讨论的哪些数据并发问题 以下是我的一个程序中
  • 更新 ConcurrentHashMap 中其他键的后果#computeIfAbsent

    Javadoc 来自ConcurrentHashMap computeIfAbsent says 计算应该简短且简单 并且不得试图 更新此地图的任何其他映射 但是 据我所知 使用remove and clear 里面的方法mappingFu
  • Java 从 ConcurrentHashMap 中删除特定项

    使用remove 方法可以吗 我读过一篇文章 说remove方法中还没有添加同步功能 如何正确删除specificConcurrentHashMap 中的项目 示例代码 ConcurrentHashMap
  • 对 java ConcurrentHashMap 中的值进行排序

    我有以下用于对 ConcurrentHashMap 进行排序的代码 ConcurrentHashMap
  • ConcurrentHashMap 抛出递归更新异常

    这是我的Java代码 static Map

随机推荐

  • 成功解决 -- An I/O error occured while sending data to the backend.

    文章目录 问题描述 历史经验 排查步骤 解决方法 问题描述 Oracle通过kettle工具同步数据到Gauss报IO错误 历史经验 应用侧 获取连接后未及时关闭 DriverManager gerConnection后未调用con clo
  • 如何查看list的维度

    在写神经网络代码过程中 总是有很多的矩阵变换 有很多时候矩阵是有list构成的 然而list又没有shape方法 无法直接查看list的维度 通过查找资料 我看到可以使用将其转化为数组的形式查看维度 代码如下 import numpy as
  • Tkinter 控件详细介绍

    Tkinter支持15个核心的窗口部件 这个15个核心窗口部件类列表如下 窗口部件及说明 Button 一个简单的按钮 用来执行一个命令或别的操作 Canvas 组织图形 这个部件可以用来绘制图表和图 创建图形编辑器 实现定制窗口部件 Ch
  • 远程桌面端口默认是什么?修改远程桌面端口号方法

    远程桌面连接是我们控制远程电脑的高效方法 远程桌面连接也是需要使用端口的 下面我们一起来学习一下远程桌面连接默认的端口号及服务器端远程端口号的修改方法 推荐 服务器远程桌面端口修改工具 远程桌面端口默认是什么 远程桌面连接的默认端口号是 3
  • C语言实现简易扫雷小游戏

    game h include
  • Linux下编译CEF源码及交叉编译

    Linux下编译CEF chromium源码及交叉编译 官方编译文档 https bitbucket org chromiumembedded cef wiki MasterBuildQuickStart markdown header l
  • 继承 c++

    1 类的继承概念的解释 2 函数隐藏 3 赋值兼容 4 多种继承方式 5 函数的使用 构造函数 析构函数 拷贝构造函数 赋值运算符重载函数 1 类的继承概念解释 假定有一个类A 要创建一个新类B 它是类A的一个特殊版本 类A就称为基类 类B
  • java前台请求quartz,spring整合java quartz实现动态定时任务的前台网页配置与管理

    实例简介 在实际项目应用中经常会用到定时任务 可以通过quartz和spring的简单配置即可完成 但如果要改变任务的执行时间 频率 废弃任务等就需要改变配置甚至代码需要重启服务器 这里介绍一下如何通过quartz与spring的组合实现动
  • 目标主机SSH服务存在RC4、CBC或None弱加密算法 修复方法

    近期进行服务器漏扫时发现了 目标主机SSH服务存在RC4 CBC或None弱加密算法 的漏洞 记录一下修复方法 如下 1 修改 ssh 配置文件 vim etc ssh sshd config 或 vi etc ssh sshd confi
  • java打印出1~100之内的所有素数

    素数 质数 是指在大于1的整数之中只能被1和它自身整除的数就称之为素数 例如 2 1 2 2 2 1 2就是一个素数 以此类推3 5 7都是素数 代码 public class Main public static void main St
  • 主板电源开关接口图解_组装电脑时主板跳线如何接?DIY装机主板接线教程

    如今装机不再像以前那么神秘 不用再去电脑城问东问西 只要上天猫或京东等网上商城即可放心买到各种电脑配件 那么 自己组装电脑最难的是什么 CPU 散热器 内存 显卡安装都很简单 很多小伙伴自己组装电脑的难点主要在于主板跳线或者说机箱接线 今天
  • 2022.06.26 华为od机试真题

    华为od机试真题 1 最长连续子串 2 正方形数量 3 二叉树层次遍历 不会做 1 最长连续子串 有N个正整数组成的一个序列 给定一个整数sum 求长度最长的的连续子序列使他们的和等于sum 返回次子序列的长度 如果没有满足要求的序列 返回
  • 2019年广东工业智能机器人产量约占全国29%

    日前发布的 广东省制造业高质量发展 十四五 规划 下称 规划 中 智能机器人是我省 十四五 谋划发展的十大战略性新兴产业之一 战略性新兴产业是科技创新和产业发展的深度融合 规划针对智能机器人的发展提出 重点发展机器人减速器 控制器等关键部件
  • 【计算机视觉

    文章目录 一 PROMISE12 二 BraTS 2015 三 LIP Look into Person 四 BigEarthNet 五 Stanford Background Standford Background Dataset 六
  • win10 powershell无法激活conda v4.9环境

    1 PATH环境变量 把condabin目录添加到环境变量中 2 初始化powershell 2 1 管理员身份运行powershell win x 弹出选项 选中 Windows PowerShell 管理员 2 2 conda init
  • python 替换_Python 实现将numpy中的nan和inf,nan替换成对应的均值

    nan not a number inf infinity 正无穷 numpy中的nan和inf都是float类型 t t 返回bool类型的数组 矩阵 np count nonzero 返回的是数组中的非0元素个数 true的个数 np
  • (python)Hex文件解析和校验

    目录 前言 Hex文件结构分析 1 利用notepad 打开hex文件 2 hex行格式 行开始 数据长度 地址 数据类型 数据 校验和 3 校验和 完整代码 总结 前言 Intel HEX文件是由一行行符合Intel HEX文件格式的文本
  • 数据赋能企服增长,构建“以客户为中心”的数字化经营体系

    目前 中国企服市场数字化需求爆发 主要表现在传统行业数字化转型加速 企服企业的服务能力得到认可 新冠疫情加速数字化进程等方面 神策数据作为大数据分析与营销科技优质服务商 结合自身数字化实践经验 总结出企服数据驱动增长的解决方案 从市场营销
  • mysql查询like多个值

    有个需求是要查询字段中code前缀是H M 81 82开头的 方法一 使用like和or select from zhy where code like H or code like M or code like 81 or code li
  • Java并发包中那些值得学习的并发工具类(空谈误国,实干兴邦,代码示范,抛砖引玉)

    首先我们通常说的并发包就是java util concurrent包及其子包 集中了Java并发的各种基础工具类 一 这个并发包在哪 上面的包就是传说中的并发包 为什么这个并发包就比较流弊呢 原因主要有以下几点 提供了几个比synchron