当前位置: 首页 > news >正文

Java并发基础:一文讲清util.concurrent包的作用

Java并发基础:一文讲清util.concurrent包的作用- 程序员古德

java.util.concurrent包是 Java 中用于并发编程的重要工具集,提供了线程池、原子变量、并发集合、同步工具类、阻塞队列等一系列高级并发工具类,使用这些工具类可以极大地简化并发编程的难度,减少出错的可能性,提高程序的效率和可维护性。

官方文档地址:https://docx.iamqiang.com/jdk11/api/java.base/java/util/concurrent/package-summary.html

Executor Framework(执行器框架)

Executor Framework是Java并发编程中一个非常强大的组件,它提供了一种标准的方法来启动、管理和控制线程的执行,执行器框架主要由接口和类组成,如Executor、Executors、ExecutorService、Future和Callable,这些组件共同协作,提供了一种灵活且高效的线程管理机制。

以下是关于执行器框架中一些关键组件的说明:

  1. Executor接口:这是执行器框架中最基本的接口,它定义了一个execute方法,用于接收一个实现了Runnable接口的对象,并启动一个新线程来执行该对象的run方法,Executor接口并不严格要求实现如何创建、调度或管理线程,这些具体实现细节由它的实现类来定义。
  2. Executors类:这是一个工具类,提供了多种类型的线程池创建方法,例如newFixedThreadPool(创建固定大小的线程池)、newCachedThreadPool(创建可缓存的线程池)和newSingleThreadExecutor(创建单线程的线程池)等,这些线程池内部实际上都是实现了ExecutorService接口的对象。
  3. ExecutorService接口:这个接口扩展了Executor接口,添加了一些用于管理和控制线程执行的方法,例如:shutdown(平滑地关闭线程池)、shutdownNow(立即关闭线程池)、awaitTermination(等待所有任务执行完毕后再关闭线程池)等,此外,ExecutorService还提供了submit方法,可以接收Runnable或Callable对象,并返回一个Future对象来跟踪任务的执行状态。
  4. Future接口和Callable接口:这两个接口通常一起使用,Callable接口类似于Runnable接口,但它允许有返回值,并且可以抛出异常,Future接口表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

下面是一个使用执行器框架的简单示例,展示了如何创建一个固定大小的线程池,提交任务,并处理返回结果,如下代码:

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Future;  public class ExecutorFrameworkExample {  public static void main(String[] args) {  // 创建一个固定大小为3的线程池  ExecutorService executor = Executors.newFixedThreadPool(3);  // 提交任务并获取Future对象  Future<String> future = executor.submit(() -> {  // 模拟耗时操作  Thread.sleep(1000);  return "任务完成";  });  // 做其他事情...  // 获取任务结果(如果任务还未完成,会阻塞等待)  try {  String result = future.get();  System.out.println(result);  } catch (Exception e) {  e.printStackTrace();  }  // 关闭线程池  executor.shutdown();  }  
}

在实际应用中,通常不会在线程池刚提交任务后就立即关闭它,而是会等待所有任务都提交完毕后再关闭,此外,future.get()方法会阻塞当前线程直到任务完成,因此在需要等待任务完成的场景下应该谨慎使用,以避免死锁或不必要的线程阻塞。执行器框架通过提供这些高级抽象,使得开发者能够更专注于任务的逻辑,而不用过多关心线程的创建、调度和管理等底层细节,从而极大地简化了并发编程的复杂性。

Concurrent Collections(并发集合)

Concurrent Collections是设计用于支持并发编程的一组数据结构,在并发编程中,当多个线程同时访问和修改共享数据时,如果没有适当的同步措施,就可能导致数据不一致和其他并发问题,为了避免这些问题,Java提供了一些线程安全的集合类,称为并发集合。并发集合位于java.util.concurrent包中,它们通过内部实现来确保多个线程可以安全地并发访问这些集合,而无需在客户端代码中进行额外的同步,这些集合使用了各种复杂的算法和数据结构来最小化线程间的竞争,从而提供更高的吞吐量。

以下是一些常见的并发集合类:

  1. ConcurrentHashMap:这是一个线程安全的HashMap实现,它允许多个线程同时读写映射表,而不会相互阻塞,它通过分段锁或其他并发控制技术(如Java 8中的ConcurrentHashMap使用的CAS操作和同步控制)来实现高并发性。
  2. CopyOnWriteArrayList:这是一个线程安全的ArrayList实现,它通过在修改时复制底层数组来实现线程安全,读取操作不需要锁定,因为它们在内部数组的一个快照上执行,而写入操作则创建一个新的数组副本,修改它,然后原子地将其替换为当前数组。
  3. ConcurrentLinkedQueue:这是一个基于链接节点的无界线程安全队列,它按照FIFO(先进先出)原则对元素进行排序,多个线程可以安全地并发访问此队列,它使用高效的非阻塞算法来实现。
  4. ConcurrentSkipListMap和ConcurrentSkipListSet:这些是基于跳表(Skip List)数据结构实现的并发有序集合,它们提供了与TreeMap和TreeSet类似的功能,但是支持更高并发的读写操作。
  5. ConcurrentLinkedDeque:这是一个双端队列(Deque),支持在队列的两端进行高效的插入和移除操作,它是线程安全的,并且允许多个线程并发访问。
  6. BlockingQueue接口及其实现:这个接口定义了一个线程安全的队列,该队列在尝试检索元素但队列为空时,会阻塞检索线程,直到队列中有元素可用,同样,当队列已满时,尝试添加元素的线程也会被阻塞,直到队列中有可用空间。ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue和SynchronousQueue等是该接口的一些常用实现。

并发集合的使用场景主要是在多线程环境中,当需要一个数据结构来安全地共享数据时,使用这些集合可以减少编写和维护复杂的同步代码的需要,同时提高程序的性能和可伸缩性。

如下是使用ConcurrentHashMap代码示例,如下代码:

import java.util.concurrent.ConcurrentHashMap;  public class ConcurrentCollectionExample {  public static void main(String[] args) {  ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();  // 多个线程可以安全地并发访问这个 map  map.put("apple", 1);  map.put("banana", 2);  System.out.println(map.get("apple")); // 输出 1  }  
}

ConcurrentHashMap是一种高效的线程安全的哈希表实现,它允许多个线程并发地读写数据,而不需要额外的同步。

Atomic Variables(原子变量)

Atomic Variables(原子变量)是并发编程中用于实现线程安全的一种机制,原子变量提供了一种在多线程环境中安全地读取、修改和更新变量的方式,而不需要额外的同步措施。在并发编程中,当多个线程同时访问和修改共享变量时,如果没有适当的同步措施,可能会导致数据不一致和其他并发问题,为了解决这个问题,通常需要使用锁或其他同步机制来确保对变量的访问是原子的。

原子变量提供了一种更简洁、高效的方式来实现线程安全的数据更新,它们通过内部机制来确保对变量的操作是原子的,从而避免了显式的同步,原子变量通常在底层使用硬件支持或特殊的指令来实现原子操作,这使得它们在性能上优于传统的同步机制。

原子变量在Java中主要通过java.util.concurrent.atomic包中的类实现,例如AtomicInteger、AtomicLong、AtomicBoolean等,这些类提供了各种原子操作方法,如incrementAndGet()、decrementAndGet()、compareAndSet()等,这些方法对底层变量执行原子操作,并返回操作后的值。

如下是使用AtomicInteger的代码示例:

import java.util.concurrent.atomic.AtomicInteger;  public class AtomicVariableExample {  public static void main(String[] args) {  AtomicInteger atomicInt = new AtomicInteger(0);  // 多个线程可以安全地并发更新这个原子整数  int oldValue = atomicInt.getAndIncrement(); // 原子性地自增并返回旧值  System.out.println(oldValue); // 输出 0  int newValue = atomicInt.get(); // 获取当前值  System.out.println(newValue); // 输出 1  }  
}

AtomicInteger提供了一种原子性地更新整数值的方法,不需要使用synchronized关键字。

在这个示例中,increment()方法原子地增加计数器的值,而getCount()方法原子地获取计数器的值,由于这些操作是原子的,因此在多线程环境中使用AtomicInteger比使用普通的int变量更安全。原子变量在并发编程中非常有用,它们简化了线程间的同步,并提供了更高的性能。

Synchronizers(同步器)

Synchronizers(同步器)是Java并发编程中用于协调线程之间同步的组件,它们提供了一种机制,使线程能够等待、通知或限制其他线程的执行。主要包括:ReentrantLock、CountDownLatch、CyclicBarrier等,这些类为开发者提供了一系列高级同步工具,以便更好地控制线程之间的交互。

以下是几个常用的同步器:

  1. ReentrantLock:这是一个互斥体,类似于内置的synchronized关键字,但提供了更多的灵活性和功能,ReentrantLock可以重入,意味着一个线程可以多次获取同一个锁,而不会导致死锁,此外,ReentrantLock还提供了更细粒度的控制,例如尝试获取锁、定时获取锁等。
  2. CountDownLatch:这是一个同步辅助工具,它允许一个或多个线程等待其他线程完成一系列操作,CountDownLatch在初始化时会设置一个计数值,然后每个线程在完成其任务后调用countDown()方法减少计数值,当计数值减至0时,所有等待的线程都会被唤醒。
  3. CyclicBarrier:CyclicBarrier是一个同步辅助工具,它允许一组线程相互等待,直到所有线程都达到某个状态后再一起执行,CyclicBarrier在初始化时会设置一个屏障(barrier)的初始阶段数,每个线程在完成其任务后调用await()方法在屏障处等待,当阶段数减至0时,所有线程继续执行。
  4. Semaphore:Semaphore是一个计数信号量,它提供了对资源的精细控制,Semaphore维护了一个许可证计数,只有获得许可证的线程才能访问受保护的资源,当线程完成对资源的访问后,它会释放一个许可证,允许其他线程获取资源。

同步器提供了一种灵活的机制来协调线程之间的同步,它们可以帮助开发者避免死锁、竞态条件和其他并发问题。

如下是CountDownLatch代码示例:

import java.util.concurrent.CountDownLatch;  public class SynchronizerExample {  public static void main(String[] args) throws InterruptedException {  int numberOfThreads = 5;  CountDownLatch latch = new CountDownLatch(numberOfThreads);  for (int i = 0; i < numberOfThreads; i++) {  new Thread(() -> {  System.out.println("Thread " + Thread.currentThread().getId() + " is ready");  latch.countDown(); // 通知 CountDownLatch 线程已准备就绪  }).start();  }  latch.await(); // 等待所有线程准备就绪  System.out.println("All threads are ready");  }  
}

在上面代码汇总,使用 CountDownLatch 来同步多个线程,确保在所有线程都准备就绪之后再继续执行主线程。

关注我,每天学习互联网编程技术 - 程序员古德

END!

相关文章:

Java并发基础:一文讲清util.concurrent包的作用

java.util.concurrent包是 Java 中用于并发编程的重要工具集&#xff0c;提供了线程池、原子变量、并发集合、同步工具类、阻塞队列等一系列高级并发工具类&#xff0c;使用这些工具类可以极大地简化并发编程的难度&#xff0c;减少出错的可能性&#xff0c;提高程序的效率和可…...

C++PythonC# 三语言OpenCV从零开发(2):教程选择

文章目录 相关专栏前言视频教学和官方文档视频教程OpenCV 官方教程最终选择我的最终选择 相关专栏 C&Python&Csharp in OpenCV 前言 OpenCV 有官方的教程和简单的视频教程&#xff1a; OpenCV 官方教程 B站也有相关的视频教学 OpenCV4 C 快速入门视频30讲 - 系列合集 …...

【嘉立创EDA-PCB设计指南】3.网络表概念解读+板框绘制

前言&#xff1a;本文对网络表概念解读板框绘制&#xff08;确定PCB板子轮廓&#xff09; 网络表概念解读 在本专栏的上一篇文章【嘉立创EDA-PCB设计指南】2&#xff0c;将设计的原理图转为了PCB&#xff0c;在PCB界面下出现了所有的封装&#xff0c;以及所有的飞线属性&…...

nodejs前端项目的CI/CD实现(二)jenkins的容器化部署

一、背景 docker安装jenkins&#xff0c;可能你会反问&#xff0c;这太简单了&#xff0c;有什么好讲的。 我最近就接手了一个打包项目&#xff0c;它是一个nodejs的前端项目&#xff0c;jenkins已在容器里部署且运行OK。 但是&#xff0c;前端组很追求新技术&#xff0c;不…...

python爬虫案例分享

当然&#xff0c;我可以分享一个基本的Python爬虫示例。这个示例将使用Python的requests库来抓取网页内容&#xff0c;然后使用BeautifulSoup库来解析和提取信息。我们将构建一个简单的爬虫来从一个示例网站抓取标题。 Python爬虫示例 目标 提取某网站的标题。 需要的库 r…...

【CC++】为什么 scanf 函数在读取字符串时不需要用取地址运算符

在C语言中如何使用 scanf 读取字符串 在C语言中&#xff0c;字符串实际上是字符数组&#xff0c;所以我们可以使用scanf函数来读取字符串。但是&#xff0c;需要注意的是&#xff0c;scanf在读取字符串时会在遇到空格、制表符或换行符时停止。因此&#xff0c;它不能用于读取包…...

Linux dirs命令教程:dirs命令详解与实例(附实例详解和注意事项)

Linux dirs命令介绍 dirs这是一个内置在shell中的命令&#xff0c;用于显示当前被记忆的目录列表。默认状态下&#xff0c;它会按照stack的方式储存目录&#xff0c;即最后加入的目录会被首先列出来。 Linux dirs命令适用的Linux版本 dirs命令在所有常见的Linux发行版中都适…...

掌握虚拟化:PVE平台安装教程与技术解析

&#x1f31f;&#x1f30c; 欢迎来到知识与创意的殿堂 — 远见阁小民的世界&#xff01;&#x1f680; &#x1f31f;&#x1f9ed; 在这里&#xff0c;我们一起探索技术的奥秘&#xff0c;一起在知识的海洋中遨游。 &#x1f31f;&#x1f9ed; 在这里&#xff0c;每个错误都…...

Godot FileDialog无法访问其它盘符的文件

问题描述 使用Godot的FileDialog对象访问Windows系统的文件&#xff0c;例如&#xff1a; func _on_hud_sig_save():var dlg FileDialog.new()dlg.set_access(FileDialog.ACCESS_FILESYSTEM)dlg.set_file_mode(FileDialog.FILE_MODE_SAVE_FILE)add_child(dlg)dlg.popup_cent…...

TestNG注释

目录 TestNG注释列表 BeforeXXX和AfterXXX注释放在超类上时如何工作&#xff1f; 使用BeforeXXX和AfterXXX TestNG注释 TestNG是一个测试框架&#xff0c;旨在简化广泛的测试需求&#xff0c;从单元测试&#xff08;隔离测试一个类&#xff09;到集成测试&#xff08;测试由…...

数据预处理 matlab 数据质量评估

知乎 数据类型转换等 Mathworks 数据预处理 概念辨析 配对是同一批样本的前后比较&#xff0c;独立是两批不同样本的的比较 独立样本是指我们得到的样本是相互独立的。配对样本就是一个样本中的数据与另一个样本中的数据相对应的两个样本。配对样本可以消除由于样本指定的不公…...

对象存储, 开源MinIO docker-compose.yml 文件

文章目录 python SDK 文档地址&#xff1a;docker-compose.yml 文件控制台使用&#xff1a;应用服务中使用样例&#xff1a; python SDK 文档地址&#xff1a; https://min.io/docs/minio/linux/developers/python/API.html docker-compose.yml 文件 version: 3services:min…...

爬虫笔记(一):实战登录古诗文网站

需求&#xff1a;登录古诗文网站&#xff0c;账号&#xff0b;密码&#xff0b;图形验证码 第一&#xff1a;自己注册一个账号&#xff0b;密码哈 第二&#xff1a;图形验证码&#xff0c;需要一个打码平台&#xff08;充钱&#xff0c;超能力power&#xff01;&#xff09;或…...

适用于 Windows 11 的 12 个最佳免费 PDF 编辑器

除了绘图等基本功能外&#xff0c;一些适用于 Windows 11 的免费 PDF 编辑器还具有 AI、OCR 识别和书签等高级功能。 我们的列表包含易于立即下载的 PDF 编辑软件工具。 这些工具不仅可以帮助转换 PDF、编辑、上传、删除、裁剪、分割、提取等。 PDF 是指便携式文档格式&…...

力扣每日一练(24-1-18)

经验一&#xff1a;不要把问题想复杂 Python&#xff1a; min_price float(inf)max_profit 0for price in prices:min_price min(min_price, price)max_profit max(max_profit, price - min_price)return max_profit C#&#xff1a; public int MaxProfit(int[] prices) {i…...

MyBatis 使用报错:org.xml.sax.SAXParseException 元素内容必须由格式正确的字符数据或标记组成

文章目录 前言问题分析解决方案方案一&#xff1a;使用 CDATA 区块&#xff0c;依然使用 “ > ” 或者 “ < ”方案二&#xff1a;使用转义字符 个人简介 前言 今天在使用 MyBatis 时出现报错&#xff1a; Caused by: org.xml.sax.SAXParseException: 元素内容必须由格式…...

PDF.js - 免费开源的 JavaScript 读取、显示 PDF 文档的工具库,由 Mozilla 开发并且持续维护

最近新项目需要处理 PDF&#xff0c;研究了 PDf.js 之后觉得很不错&#xff0c;于是写篇文章推荐给大家。 PDF.js 的功能和它的名字一样简单&#xff0c;是一个使用 HTML5 技术来让前端网页支持读取、解析和显示 PDF 文档的 JS 工具库。这个项目由大名鼎鼎的 Mozilla 组织开发…...

UI开发布局-HarmonyOS应用UI开发布局

UI页面的构建不用再像Android开发过程中在.xml文件中书写&#xff0c;可直接在页面上使用声明式UI的方式按照布局进行排列&#xff0c;构建应用的页面。 如下代码使用Row、Column构建一个页面布局&#xff0c;在页面布局中添加组件Text、Button&#xff0c;共同构成页面&#…...

大数据开发之Hadoop(完整版+练习)

第 1 章&#xff1a;Hadoop概述 1.1 Hadoop是什么 1、Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2、主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 3、Hadoop通常是指一个更广泛的概念-Hadoop生态圈 1.2 Hadoop优势&#xff08;4高&#xf…...

Redis与DB数据一致性-个人总结

缓存读写策略: Cache-Aside Pattern 读缓存: 先查询缓存&#xff0c;存在则返回, 如果不存在则查询DB, 再塞回缓存中,最后返回结果. 写缓存: 更新完成DB之后&#xff0c;删除缓存. 适合场景: 读比较多的场景&#xff0c;更新比较少的场景. 像我们工作当中&#…...

高性价比塑料链板输送机厂家排行适配指南

随着2026年《工业输送设备安全生产通用规范》正式落地&#xff0c;国内输送设备行业的准入门槛和生产标准迎来新一轮调整&#xff0c;新规对各领域使用的输送设备提出了更明确的合规要求&#xff0c;也给中小企业选购设备提供了清晰的参考标准。2026年输送设备安全生产新规核心…...

Redis分布式锁进阶第一十一篇

一、本篇前置衔接 第一十一篇我们完成了全系列终局复盘&#xff0c;整理了故障排查SOP与企业级落地铁律。常规单资源锁、热点分片锁、隔离锁全部讲透&#xff0c;但真实复杂业务永远不是单一资源&#xff1a;下单要扣库存、扣优惠券、扣积分、冻结余额&#xff0c;多资源并行争…...

ElevenLabs支持闽南语吗?福建话语音合成实测:从API调用到音色克隆的7步通关手册

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs福建话语音支持现状与能力边界 ElevenLabs 目前尚未在官方语音模型库中提供对福建话&#xff08;含闽南语、闽东语等分支&#xff09;的原生支持。其公开文档与 API 文档均未列出任何以“Fuj…...

边缘AI框架:在边缘设备上运行AI模型

边缘AI框架&#xff1a;在边缘设备上运行AI模型 一、边缘AI框架概述 1.1 边缘AI框架的定义 边缘AI框架是指用于在边缘设备上部署和运行AI模型的软件框架。它提供了模型优化、推理加速和设备适配等功能&#xff0c;使得AI模型能够在资源受限的边缘设备上高效运行。 1.2 边缘AI框…...

开源 AI Agent Harness Engineering 模型与闭源模型的对比

开源 AI Agent Harness Engineering 模型与闭源模型的对比 摘要 如果把AI Agent比作自动驾驶汽车&#xff0c;那么AI Agent Harness就是这辆车的操作系统&#xff1a;它负责管控任务规划、工具调用、记忆管理、容错重试等所有核心逻辑&#xff0c;是Agent落地工程化的核心支撑…...

如何在Mayo中使用剪辑平面和爆炸视图:复杂装配体分析利器

如何在Mayo中使用剪辑平面和爆炸视图&#xff1a;复杂装配体分析利器 【免费下载链接】mayo 3D CAD viewer and converter based on Qt OpenCascade 项目地址: https://gitcode.com/gh_mirrors/ma/mayo Mayo是一款功能强大的开源3D CAD查看器和转换器&#xff0c;基于Q…...

BetterCodable高级用法:自定义策略和属性包装器的深度解析

BetterCodable高级用法&#xff1a;自定义策略和属性包装器的深度解析 【免费下载链接】BetterCodable Better Codable through Property Wrappers 项目地址: https://gitcode.com/gh_mirrors/be/BetterCodable BetterCodable是一个通过属性包装器(Property Wrapper)增强…...

软考系统架构设计师实战论文集:自动驾驶与AI云端架构演进

【引言】 自动驾驶的下半场&#xff0c;早已不再局限于单车智能的角逐&#xff0c;而是演变成了一场关乎云端算力、海量数据治理与大模型工程化的全面战役。当接入的车辆规模突破百万级&#xff0c;当每日回传的工况数据达到 PB 级&#xff0c;云端数据平台的可靠性、扩展性与…...

如何优化鸿蒙 App 的启动速度?

子玥酱 &#xff08;掘金 / 知乎 / CSDN / 简书 同名&#xff09; 大家好&#xff0c;我是 子玥酱&#xff0c;一名长期深耕在一线的前端程序媛 &#x1f469;‍&#x1f4bb;。曾就职于多家知名互联网大厂&#xff0c;目前在某国企负责前端软件研发相关工作&#xff0c;主要聚…...

vue3+python基于Django的羽毛球场地预约服务管理系统设计与实现869373194

目录同行可拿货,招校园代理 ,本人源头供货商项目概述技术栈核心功能模块系统设计要点扩展功能部署方案项目技术支持源码获取详细视频演示 &#xff1a;同行可合作点击我获取源码->->进我个人主页-->获取博主联系方式同行可拿货,招校园代理 ,本人源头供货商 项目概述 …...