突破瓶颈:Java并发编程的最佳实践与技巧,你了解了吗?

在这里插入图片描述

文章目录

    • 1 什么是 Executor 和 ExecutorService ?这两个接口有什么区别?
    • 2 java.util.concurrent 标准库中 ExecutorService 的可用实现是什么 ?
    • 3 什么是 Java 内存模型( JMM )?描述下其目的和基本思想
    • 4 JMM 对添加了 final 修饰符的类的字段有什么特殊保证 ?

1 什么是 Executor 和 ExecutorService ?这两个接口有什么区别?

ExecutorExecutorService 是用于处理并发任务的两个接口。

Executor 主要用于基本的任务提交,适用于简单的线程管理需求,而 ExecutorService 提供了更多的功能,适用于需要更复杂的任务控制和线程管理的场景。

Executor 是一个简单的接口,它只定义了一个方法 execute(Runnable command),用于执行 Runnable 对象,这个方法将 Runnable 对象提交给执行器,然后执行器在适当的线程上运行这个任务。

// 使用一个固定大小的线程池来执行任务
Executor executor = Executors.newFixedThreadPool(10);
executor.execute(() -> System.out.println("任务运行ing"));

ExecutorService 继承自 Executor,提供了更多的功能,它允许在执行任务时进行更多的控制和管理,比如提交 Callable 任务、取消任务和关闭执行器等。ExecutorService 提供的方法包括 submit() 用于提交任务并获得结果,shutdown() 用于平稳关闭执行器等。

ExecutorService executorService = Executors.newFixedThreadPool(10);
// submit() 方法提交了一个 Callable 任务,并返回一个 Future 对象,用于获取任务的结果
Future<Integer> future = executorService.submit(() -> {
    // 任务逻辑
    return 123;
});
// 用于关闭执行器,停止接受新任务并在所有已提交任务完成后关闭线程池
executorService.shutdown();

2 java.util.concurrent 标准库中 ExecutorService 的可用实现是什么 ?

ExecutorService 提供了多种实现,每种实现都有其特定的用途和特点,常见的实现包括 ThreadPoolExecutorScheduledThreadPoolExecutorForkJoinPool

ThreadPoolExecutor 是最基础的实现,它通过维护一个线程池来处理任务。可以创建固定大小的线程池,也可以设置线程池的最大和最小线程数。

使用 Executors.newFixedThreadPool(int nThreads) 方法创建一个固定线程数的线程池:

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> System.out.println("任务执行ed"));

ScheduledThreadPoolExecutor 扩展了 ThreadPoolExecutor,支持任务的定时和周期性执行。

使用 Executors.newScheduledThreadPool(int corePoolSize) 可以创建一个支持定时任务的线程池:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
scheduler.scheduleAtFixedRate(() -> System.out.println("定时任务"), 0, 1, TimeUnit.SECONDS);

ForkJoinPool 专注于大规模并行计算,适用于分而治之的任务模型,它特别适合处理递归任务,可以高效地将任务分解成多个子任务,然后将结果合并。

使用 ForkJoinPool 可以执行分解任务的操作:

ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.submit(() -> {
    // 递归任务逻辑
}).join();

3 什么是 Java 内存模型( JMM )?描述下其目的和基本思想

Java 内存模型(JMM)可以比喻成一个图书馆的借书系统。这个系统的目的是确保所有的借书和还书记录在所有的图书馆分馆之间都是一致的。无论你在哪个分馆借书或还书,系统都会确保你得到的是最新的、准确的书籍记录。

Java 内存模型(JMM)定义了 Java 程序中线程如何与内存进行交互的规则,它的主要目的是确保多线程环境下的程序行为是可预测的,避免由于线程间的并发访问导致的不一致性和不可预期的错误。

JMM 主要关注两个方面:内存可见性和指令重排序。

内存可见性就像图书馆的借书记录需要在所有分馆同步一样,JMM 确保当一个线程修改了共享数据,其他线程能及时看到这个修改。

内存可见性指的是当一个线程修改了共享变量的值,其他线程能够及时看到这个变化。为了保证这一点,JMM 规定了在不同线程之间的数据同步必须通过特定的操作,比如使用 synchronized 关键字或 volatile 关键字。

使用 synchronized 能够确保在进入一个同步块时,所有之前对共享变量的修改对当前线程是可见的;同样,当线程退出同步块时,对共享变量的修改也会被及时刷新到主内存中。

private int counter = 0;

public synchronized void increment() {
    counter++;
}

public synchronized int getCounter() {
    return counter;
}

指令重排序就像图书馆系统需要确保借书和还书的记录按正确的顺序处理。

指令重排序是指编译器或处理器可能会对程序中的指令进行重新排列,以提高性能。虽然这种优化对于单线程程序通常是透明的,但在多线程环境中可能导致意外的行为。

JMM 通过引入内存屏障volatile 关键字来规范指令执行的顺序,从而避免指令重排序带来的问题。

声明一个变量为 volatile 可以确保这个变量的读写操作不会被重排序:

private volatile boolean flag = false;

public void setFlag() {
    flag = true;
}

public boolean checkFlag() {
    return flag;
}

JMM 通过这些规则和机制来实现多线程程序的正确性和一致性,确保程序在并发执行时能够以预期的方式运行,而不受硬件和编译器优化的影响,使得 Java 的多线程编程更具可预测性和可靠性。

4 JMM 对添加了 final 修饰符的类的字段有什么特殊保证 ?

final 字段比作一个已经封好的信封。假设你把一封信(即 final 字段)写好并封好(初始化完成),然后把它交给别人(其他线程)。一旦信封封好并且交给了别人,信封中的内容就不会再改变。其他人只要拿到这个信封,就可以确信里面的内容是完整和准确的,没有被修改过的可能性。

在 Java 内存模型中,给字段添加 final 修饰符会带来特别的保证,final 修饰的字段在对象构造完成后,会有一项确保该字段不会被改变的约束。

这样做的好处是,它保证了在构造器中对该字段的所有写入操作在其他线程看到对象时都是可见的,且这些写入操作不会被重排序,确保了对象的正确初始化。

有一个类 Person,它有一个 final 字段 name

public class Person {
    // Person 对象创建完成,name 的值就不能再改变
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Java 的内存模型保证了在对象的构造完成后,所有线程都能看到 name 字段的正确值。这是因为构造完成后,final 字段的值写入将会被正确地发布到其他线程中,避免了由于内存重排序或缓存导致的读取不一致。

特别地,当一个对象被完全构造好并且对外可见时,所有 final 字段的值都已被正确地初始化。

这种保证也意味着,如果一个线程看到一个对象的 final 字段,那么它也能看到该对象的其他 final 字段及构造过程中的所有必要的初始化步骤。这就是 final 关键字在多线程环境中提供的内存可见性保证,使得 final 字段成为线程安全的。

在人生的旅途中,一定要学会自己拯救自己,这样才能在逆境中奋勇前行

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

工业相机飞拍的原理及工作原理

工业相机飞拍&#xff08;或称为工业高速相机飞行拍摄&#xff09;是一种利用高速图像捕捉技术和精密运动控制系统进行高效图像采集的先进技术。它广泛应用于工业检测、质量控制和自动化生产等领域。本文将详细探讨工业相机飞拍的原理及其工作方式。 一、工业相机飞拍的基本概…

插件第一版基本完成

什么插件 Command Assist 经过多次修改和界面优化&#xff0c;Mac和Windows的适配&#xff0c;最终形态长这样&#xff1a; 欢迎下载使用&#xff0c;反馈问题和建议~ 主要作为日常开发的手边工具&#xff0c;功能不复杂&#xff0c;核心就是常用命令的管理&#xff0c;包括&…

35天学习小结

距离上次纪念日&#xff0c;已经过去了35天咯 算算也有5周了&#xff0c;在这一个月里&#xff0c;收获的也挺多&#xff0c;在这个过程中认识的大佬也是越来越多了hh 学到的东西&#xff0c;其实也没有很多&#xff0c;这个暑假多多少少还是有遗憾的~ 第一周 学习了一些有…

Good Die与Inked Die 介绍

Good Die与Inked Die在半导体行业中,特别是与闪存芯片相关的领域,是两个重要的概念,它们代表了芯片质量的不同等级。 Good Die 定义: Good Die,即良品颗粒,是指在晶圆生产过程中,经过严格测试后被认定为符合原厂规格要求、质量良好的芯片。这些芯片在切割、封装等后续工…

第15-02章:理解Class类并获取Class实例

我的后端学习大纲 我的Java学习大纲 1、Java反射机制原理图&#xff1a; 源代码通过Javac编译得到字节码文件&#xff0c;当我执行到new一个对象的时候&#xff0c;字节码文件会通过ClassLoader被加载&#xff0c;然后得到一个Class类对象&#xff0c;存放在堆中&#xff0c;加…

Redis搭建集群

功能概述 Redis Cluster是Redis的自带的官方分布式解决方案&#xff0c;提供数据分片、高可用功能&#xff0c;在3.0版本正式推出。 使用Redis Cluster能解决负载均衡的问题&#xff0c;内部采用哈希分片规则&#xff1a; 基础架构图如下所示&#xff1a; 图中最大的虚线部分…

Linux的历史,版本,Linux的环境安装、简单学习4个基本的Linux指令、创建普通用户等的介绍

文章目录 前言一、Linux的历史二、版本三、Linux的环境安装1. 腾讯云服务器的申请2. xshell的安装与使用 四、 简单学习4个基本的Linux指令1. ls2. pwd3. mkdir4. cd 五、创建普通用户总结 前言 Linux的历史&#xff0c;版本&#xff0c;Linux的环境安装、简单学习4个基本的Li…

PHP随时随地预订民宿酒店预订系统小程序源码

随时随地预订&#xff0c;民宿酒店预订系统让旅行更自由&#xff01; &#x1f30d; 说走就走的旅行&#xff0c;从预订开始 旅行&#xff0c;总是让人心生向往&#xff0c;但繁琐的预订流程却常常让人望而却步。不过&#xff0c;现在有了“随时随地预订民宿酒店预订系统”&am…

RK3588九鼎创展方案在Arm集群服务器的项目中的应用分析​​

RK3588九鼎创展核心板&#xff0c;搭载8核瑞芯微3588芯片&#xff0c;具备高性能、低功耗以及强大的多媒体和AI处理能力。在Arm集群服务器项目中&#xff0c;RK3588系列芯片用有明显的性能优势。本文将结合RK3588芯片的性能特征以及九鼎创展的项目经验来分析RK3588在集群服务器…

【JAVA入门】Day34 - Stream流

【JAVA入门】Day34 - Stream流 文章目录 【JAVA入门】Day34 - Stream流一、Stream 流的作用和使用步骤1.Stream流的创建&#xff0c;数据的添加2. Stream流的中间方法3. Stream流的终结方法 Stream 流有什么作用&#xff1f;我们看一个例子&#xff1a; 【练习】需求&#xff…

swift qwen2-vl推理及加载lora使用案例

参考: https://swift.readthedocs.io/zh-cn/latest/Instruction/LLM%E5%BE%AE%E8%B0%83%E6%96%87%E6%A1%A3.html#%E5%BE%AE%E8%B0%83%E5%90%8E%E6%A8%A1%E5%9E%8B https://blog.csdn.net/weixin_42357472/article/details/142150209 SWIFT支持300+ LLM和50+ MLLM(多模态大模型…

利用高德+ArcGIS优雅获取任何感兴趣的矢量边界

荷花十里&#xff0c;清风鉴水&#xff0c;明月天衣。 四时之景不同&#xff0c;乐亦无穷尽也。今天呢&#xff0c;梧桐君给大家讲解一下&#xff0c;如何利用高德地图&#xff0c;随机所欲的获取shp边界数据。 文章主要分成以下几个步骤&#xff1a; 首先搜索你想获取的矢量…

发送成绩的app或小程序推荐

老师们&#xff0c;新学期的第一次月考马上开始&#xff0c;是不是还在为如何高效、便捷地发布成绩而头疼呢&#xff1f;别担心&#xff0c;都2024年了&#xff0c;我们有更智能的方式来解决这个问题&#xff01; 给大家安利一个超级实用的工具——易查分小程序。这个小程序简…

element ui form 表单出现英文提示的解决方案

场景再现&#xff1a; 在使用 form 表单的时候&#xff0c;一般都需要对表单元素进行验证&#xff0c;错误就出现在了这里&#xff0c;除了配置的错误信息&#xff0c;还会出现一个 英文校验提示&#xff0c;如下图&#xff1a; 解决方案 出现的原因是在el-form-item中使用…

把设计模式用起来(3)用不好的原因之时机不对

上一篇&#xff1a;《把设计模式用起来&#xff08;3&#xff09;——用不好的原因 之 实践不足》https://blog.csdn.net/nanyu/article/details/141939342 本篇继续讲设计模式用不好的常见原因&#xff0c;这是第二个&#xff1a;使用设计模式的时机不对。 二、时机不对 这里…

望繁信科技与华恒生物正式签约,共同开启流程数字化转型新篇章

近日&#xff0c;上海望繁信科技有限公司&#xff08;简称“望繁信科技”&#xff09;与安徽华恒生物科技股份有限公司&#xff08;简称“华恒生物”&#xff09;成功举行了战略合作签约仪式。作为全球领先的合成生物制造企业&#xff0c;华恒生物将引入望繁信科技的流程智能管…

3分钟带你了解什么是数据目录

什么是数据目录&#xff1f; 数据目录&#xff0c;顾名思义就是“数据的目录”。这里的“数据”指的是元数据。数据目录通过管理这些元数据&#xff0c;形成一个可用的数据清单&#xff0c;使数据开发者、数据分析师等人员能够通过查阅和搜索等操作&#xff0c;快速找到所需的数…

4052A/4052B/4052C/4052D/4052E/4052F/4052G /4052H信号/频谱分析仪

4052A/4052B/4052C/4052D/4052E/4052F/4052G /4052H信号/频谱分析仪 苏州新利通 Ceyear 4052具备出色的测试动态范围、相位噪声、幅度精度和测试速度&#xff0c;具备频谱分析、I/Q分析、实时频谱分析、瞬态分析、矢量信号分析、脉冲分析、音频分析等丰富的测试功能。 Ceyear…

长沙自闭症寄宿学校推荐,为孩子开启光明未来

在长沙这座历史悠久而又充满活力的城市中&#xff0c;自闭症儿童的成长与教育问题牵动着无数家庭的心。家长们渴望为孩子找到一所能够提供专业康复、温馨关怀与全面教育的学校&#xff0c;为他们的未来铺设一条光明之路。虽然本文起始于长沙的期盼&#xff0c;但我们的目光已跨…

SpringSecurity原理解析(二):认证流程

1、SpringSecurity认证流程包含哪几个子流程&#xff1f; 1&#xff09;账号验证 2&#xff09;密码验证 3&#xff09;记住我—>Cookie记录 4&#xff09;登录成功—>页面跳转 2、UsernamePasswordAuthenticationFilter 在SpringSecurity中处理认证逻辑是在UsernamePas…