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

  • java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock

    原文地址 xff1a https cloud tencent com developer article 1509556 今天突然被一个同事问到java8为何放弃分段锁 xff0c 于是花了点时间针对这个问题进行了小小的总结 jdk1 7分
  • HashMap、ConcurrentHashMap 一行代码实现批量删除元素

    我不想迭代器遍历 xff0c 想找个短点的方式 xff0c 但是查了一下没满意的 xff0c 自己搞一个 xff0c 比较初级的代码 span class token keyword public span span class token
  • ConcurrentHashMap优点与源码剖析

    哈希表是中非常高效 xff0c 复杂度为O 1 的数据结构 xff0c 在Java开发中 xff0c 我们最常见到最频繁使用的就是HashMap和HashTable xff0c 但是在线程竞争激烈的并发场景中使用都不够合理 HashMap
  • ConcurrentHashMap、synchronized与线程安全

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

    原博客 https www cnblogs com lujiango p 7580558 html http www importnew com 28263 html CouncurrentHashMap 线程安全 一 Councurren
  • ConcurrentHashMap详解

    目录 ConcurrentHashMap介绍 ConcurrentHashMap底层数据结构 ConcurrentHashMap部分分析 ConcurrentHashMap与HashMap HashTable的区别 源码为jdk1 7 Co
  • 【Java并发】FutureTask-Callable设置接口超时限制

    目录 代码 运行 代码 原理是新建一个Callable线程 call方法可以返回对象 用FutureTask封装后 通过future对象的get方法来设定超时限制 如果超时 则future cancel true 取消执行 重写Callab
  • 前端异步编程的进化之旅 promise generator aysnc/await

    promise generator aysnc await 1 三者都是异步编程的解决方案 不同的是 promise为较早出来的 其次generator 最后为async await 三者象征了前端进行解决异步编程的进化路程 promise
  • Javascirp异步编程

    在上一篇彻底弄清Javascirpt中的同步和异步一问当中 介绍了Javascirp代码执行的概念 同步和异步的原理 学习过Javascript语言的同学都知道 从Javascript诞生之日起 就是一门单线程 非阻塞的脚本语言 Javas
  • 线程基础---基础方法

    线程启动 在Thread类中注释标明有两种方式创建新的执行线程 一种是声明一个类是Thread的子类 这个子类应该重写类Thread的run方法 然后可以分配和启动子类的实例 创建线程的另一种方法是声明一个实现Runnable接口的类 这个
  • 一篇文章,从源码深入详解ThreadLocal内存泄漏问题

    原创文章 经验总结 从校招到A厂一路阳光一路沧桑 详情请戳www coderccc com 1 造成内存泄漏的原因 threadLocal是为了解决对象不能被多线程共享访问的问题 通过threadLocal set方法将对象实例保存在每个线
  • 异步编程(async 和 await)

    1 概念 异步编程是一项关键技术 可以直接处理多个核心上的I O阻塞和并发操作 2 使用场景 对于存在IO密集型 例如从网路请求数据 访问数据库和写入到文件系统 和CPU密集型 例如大量的计算 的任务可以选择异步编程 3 异步编程针对于IO
  • HashMap/ConcurrentHashMap在单线程模式下的性能比较

    起源 阅读源码发现jdk8中ConcurrentHashMap是基于synchronized来加锁实现多线程安全的 但是实现方式上与早期的HashTable又有了很大的区别 虽然都是使用synchronized来加锁 但是锁的粒度不一样 大
  • JAVA并发-Monitor简介

    什么是Monitor 1 Monitor是一种用来实现同步的工具 2 与每个java对象相关联 即每个java对象都有一个Monitor与之对应 3 Monitor是实现Sychronized 内置锁 的基础 Monitor的基本结构是什么
  • 高并发模拟~多个线程同时发起请求

    高并发模拟 多个线程同时发起请求 两种方案 CyclicBarrier 栅栏 所有的线程必须同时到达栅栏位置 才能继续执行 CountDownLatch 计数器 一个线程或多个线程一直等待 直到其他线程执行的操作完成 1 CyclicBar
  • ConcurrentHashMap的Segment和HashMap的Bucket理论上有什么区别?

    我知道在HashMap中 条目 Key Value 基于hash Key hashCode gt 表示存储桶位置的索引 如果条目已放置在该位置 则会创建一个链接列表和新条目 如果它有不同的键 gt 通过equals method 被放置在链
  • Java ConcurrentHashMap 中增加分区数量的缺点?

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

    我想知道当我们尝试在 ConcurrentHashMap 调整大小时读取它时可能发生的情况 我知道在读取期间 第一次尝试总是不同步的 在第二次尝试中 它将尝试获取锁并重试 但如果在调整大小期间发生这种情况 它将如何工作 Thanks 通过查
  • 更新 ConcurrentHashMap 中其他键的后果#computeIfAbsent

    Javadoc 来自ConcurrentHashMap computeIfAbsent says 计算应该简短且简单 并且不得试图 更新此地图的任何其他映射 但是 据我所知 使用remove and clear 里面的方法mappingFu
  • Java ConcurrentHashMap 不是线程安全的..什么?

    我之前使用过 HashMap public 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