【JavaEE初阶】JUC(java.uitl.concurrent)的常见类

news2024/9/25 17:18:30

🌴Callable 接口

之前讲到Runnable接口,用于描述一个任务,通过Runnable中的run方法来体现的,但是描述的任务没有返回值(run方法是返回void),此处的Callable接口与Runnable接口类似,Callable里面的call方法是有返回值,表示这个线程执行结束要得到的结果是啥

 比如我们有以下需求

创建线程计算 1 + 2 + 3 + … + 1000, 如果我们不使用Runnable

使用 Runnable 的实现过程如下:

代码:

这个代码就相当于是让sum在t线程也使用,主线程也使用,这样使主线程和t1线程耦合太大了,若线程较多,就会更加麻烦。

使用Callable就是为了更优雅的解决上述问题

使用 Callable的实现过程如下:

  • 创建一个匿名内部类, 实现 Callable 接口. Callable 带有泛型参数. 泛型参数表示返回值的类型.
  • 重写 Callable 的 call 方法, 完成累加的过程. 直接通过返回值返回计算结果.
  • 把 callable 实例使用 FutureTask 包装一下.
  • 创建线程, 线程的构造方法传入 FutureTask . 此时新线程就会执行 FutureTask 内部的 Callable 的call 方法, 完成计算. 计算结果就放到了 FutureTask 对象中.
  • 在主线程中调用 futureTask.get() 能够阻塞等待新线程计算完毕. 并获取到 FutureTask 中的结果

注意:不是直接将 Callable 引言直接传给Thread,Thread并没有这种构造方法来传入Callable。

标准库提供了一个"辅助"的类,借助这个"辅助"的类对Callable进行包装一层(FutureTask)

总结:

  • Callable 和 Runnable 相对, 都是描述一个 “任务”. Callable 描述的是带有返回值的任务,
  • Runnable 描述的是不带返回值的任务.
  • Callable 通常需要搭配 FutureTask 来使用. FutureTask 用来保存 Callable 的返回结果. 
  • Callable 往往是在另一个线程中执行的, 啥时候执行完并不确定.
  • FutureTask 就可以负责这个等待结果出来的工作

举个例子可以更好的理解理解 FutureTask:

我们在吃麻辣烫的时候,选完菜之后,服务员都会给我一张小票(取餐号),这个小票就相当于使FutureTask,后面我们可以随时凭这张小票去查看自己的这份麻辣烫做出来了没

🚩 相关面试题:

🎄ReentrantLock

首先怎么读:Re 鹌鹑 t  唠嗑

ReentrantLock是可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全

我们从字面意思上就可以知道 “Reentrant” 这个单词的原意就是 "可重入”,

所以ReentrantLock 也是可重入锁。

🚩ReentrantLock 的用法

  • lock(): 加锁, 如果获取不到锁就死等.

  • trylock(超时时间): 加锁, 如果获取不到锁, 等待一定的时间之后就放弃加锁.

  • unlock(): 解锁

我们在使用ReentrantLock 的时候,我们可能会忘记解锁(如在加锁之后判定条件里面有return,或者抛异常......),若确实要使用ReentrantLock,搭配finally来使用,将解锁操作放到finally中

代码:

🚩ReentrantLock 和 synchronized 的区别

  • synchronized 只是非公平锁,ReentrantLock 提供了公平锁的实现(默认是非公平锁,需要在构造这个对象的时候,指定一个参数true,才为公平锁)

  • ReentrantLock提供tryLock操作,给加锁提供了更多的可操作空间,尝试加锁,如果锁已经被获取到了,直接返回失败,而不会继续等待

  • 更强大的唤醒机制.
    synchronized 是通过 Object 的 wait / notify 实现等待-唤醒.每次唤醒的是一个随机等待的线程.
    ReentrantLock 搭配 Condition 类实现等待-唤醒, 可以更精确控制唤醒某个指定的线程.
  • synchronized 使用时不需要手动释放锁. ReentrantLock 使用时需要手动释放. 使用起来更灵活,但是也容易遗漏 unlock.

🚩如何选择使用哪个锁?

在实际应用中我们该如何选择锁呢?

  • 锁竞争不激烈的时候, 使用 synchronized, 效率更高, 自动释放更方便.

  • 锁竞争激烈的时候, 使用 ReentrantLock, 搭配 trylock 更灵活控制加锁的行为, 而不是死等.

  • 如果需要使用公平锁, 使用 ReentrantLock

大部分场景都是用 synchronized。

🎍原子类

之前讲过,原子类内部用的是 CAS 实现,所以性能要比加锁实现 i++ 高很多。原子类有以下几个

  • AtomicBoolean

  • AtomicInteger

  • AtomicIntegerArray

  • AtomicLong

  • AtomicReference

  • AtomicStampedReference

这里以 AtomicInteger 举例,常见方法有:

🎋线程池

线程池在前面也讲述过,这里不在讨论~~

🌳信号量 Semaphore

读法:se mer fo

信号量, 用来表示 “可用资源的个数”. 本质上就是一个计数器

听起来高大上,其实不难理解:

可以把信号量想象成是停车场的展示牌: 当前有车位 100 个. 表示有 100 个可用资源.
当有车开进去的时候, 就相当于申请一个可用资源, 可用车位就 -1 (这个称为信号量的 P 操作)
当有车开出来的时候, 就相当于释放一个可用资源, 可用车位就 +1 (这个称为信号量的 V 操作)
如果计数器的值已经为 0 了, 还尝试申请资源, 就会阻塞等待, 直到有其他线程释放资源

围绕信号量有两个基本操作:

  • P 操作 计数器 -1  申请资源
  • V 操作 计数器 +1 释放资源

代码:

  • 创建 Semaphore 示例, 初始化为 4, 表示有 4 个可用资源.

  • acquire 方法表示申请资源(P操作), release 方法表示释放资源(V操作)

注意:        

使用信号量解决线程安全问题:

🍀 CountDownLatch

相对来说比较实用的工具类,当我们把一个任务拆分成多个的时候,就可以通过这个工具类来识别任务是否整体执行完毕。

CountDownLatch的作用为:同时等待 N 个任务执行结束

把一个大文件拆分成20个部分,每个线程都独立和人家服务器建立连接,分20个连接进行下载,等所有线程下载完毕之后,再将结果进行合并,就需要通过CountDownLatch来识别出所有线程都执行完毕。

接下来我们依旧用代码实例进行讲解:

  • 构造 CountDownLatch 实例, 初始化 10 表示有 10 个任务需要完成.
  • 每个任务执行完毕, 都调用 latch.countDown() . 在 CountDownLatch 内部的计数器同时递减.
  • 主线程中使用 latch.await(); 阻塞等待所有任务执行完毕. 相当于计数器为 0

代码:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLVM理论篇之编译器前端

1、简述 LLVM前端通过对源程序的预处理,构成源程序的字符流扫描与分解,将单词序列提取为各类语法短语,生成抽象语法树,最终转换为中间代码。编译器前端包含的这几个过程如下: (1)预编译 &…

【python】实现对文件夹中的图像连续重命名方法

import os import shutildef rename_images(input_folder):# 获取输入文件夹下的所有图片文件(假设都是.jpg格式)image_files [f for f in os.listdir(input_folder) if os.path.isfile(os.path.join(input_folder, f)) and f.endswith(".jpg"…

性能测试工具LoadRunner

前言👀~ 上一章我们介绍了性能测试的一些基本概念,重要的是性能测试的各项指标,今天我们使用性能测试工具LoadRunner简单的完成一次性能测试 性能测试Load Runner LoadRunner是什么? LoadRunner安装 LoadRunner脚本录制 1.录…

振弦式钢筋计的主要应用领域有哪些?

在现代工程建设中,钢筋作为重要的结构材料,其应力状态直接关系到工程结构的安全性和稳定性。因此,对钢筋应力的实时监测成为了保障工程质量的关键环节。振弦式钢筋计作为一种高精度、稳定性好的应力监测仪器,在桥梁、建筑、隧道等…

pg一些常用语句记录

查看数据库大小 pg_size_pretty:将数据库用量展示为KB、MB、GB等样式,查看更直观查看具体某个数据库的大小 select pg_size_pretty(pg_database_size(postgres)); 查看所有数据库的大小 select pg_database.datname, pg_size_pretty (pg_database_size(pg_database.datnam…

Sqli-labs-master靶场--布尔盲注

目录 1、布尔盲注 2、布尔盲注的流程(以靶场less-8为例) 2.1输入id尝试是否存在注入点 2.1.1通过以上尝试,联想到可能是布尔盲注 2.2猜测数据库长度 2.3获取数据库名 2.3.1python脚本获取 代码: 获取结果为: …

后期调色学习笔记

关于调色曲线的学习: 学习链接:一看就懂的曲线调色教程【手机摄影后期】_哔哩哔哩_bilibili 从左向右就是由暗部越来越到亮部 越靠近右侧的越是亮部

机械学习—零基础学习日志(数学基础汇总1)

零基础为了学人工智能,正在艰苦的学习 我比较推荐,《三个月从零入门深度学习,保姆级学习路线图》的整体学习思路,但因为数学基础太差,而且针对所需的数学系统知识,我依然没有很明确的学习方向。 所以直接…

杀手级的AI LLM产品还有多久面世

AI产品落地:Killer App依然缺席的原因与未来展望 🚀 在当今科技领域,人工智能(AI)无疑正处于一个快速发展的阶段。尽管如此,关于AI产品的实际应用和市场落地,仍然存在诸多挑战。本文将探讨当前…

使用 Matplotlib 绘制折线图

使用 Matplotlib 绘制折线图 数据可视化是数据分析的重要组成部分,通过图表,我们可以更直观地理解数据背后的趋势和模式。Matplotlib 是 Python 最基础也是最常用的绘图库之一,非常适合初学者。本文将带你从零开始,逐步创建和自定…

Python Static Typing: 提升代码可靠性与可读性的使用技巧

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…

Java毕业设计 基于SSM和Vue的酒店管理系统小程序

Java毕业设计 基于SSM和Vue的酒店管理系统小程序 这篇博文将介绍一个基于SSM框架和Vue开发的酒店管理系统微信小程序,适合用于Java毕业设计。 功能介绍 用户 登录 注册 忘记密码 首页 图片轮播 房间信息 房间详情 预订 收藏 评论 我的 订单信息 酒店管理…

Python 常用内置函数

目录 1、enumerate函数 1.1、for循环中使用 1.2、enumerate指定索引的起始值 1.3、enumerate在线程中的作用 2、Map 函数 2.1、map()函数可以传多个迭代器对象 3、lambda表达式(匿名函数) 示例 4、sort函数和sorted函数 4.1、sort()函数 4.2、…

vue2学习 -- vuex

文章目录 1. 理解2. 语法2.1 安装使用2.2 getters配置项2.3 四个map方法的使用2.4 vuex模块化 1. 理解 概念:专门在ue中实现集中式状态(数据)管理的一个ue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写&…

Java基础 1. Java开发环境搭建

Java基础 1. Java开发环境搭建 文章目录 Java基础 1. Java开发环境搭建1.1. 常用的DOS命令1.1.1. 常用的Windows组合键:1.1.2. 常用的DOS命令:1.1.3. 批处理文件 1.2. 通用文本编辑快捷键1.2.1. Sublime Text文本编辑器的安装与使用安装中英文打开方式调整字体大小文件扩展名 1…

LlamaIndex 如何可视化跟踪日志

LlamaIndex 中无论是 RAG 还是 Agent,都是需要和 LLM 进行交互,在这个流程流中包括搜索、Retrieve和推理等多个阶段。提示词在整个流程通过模板进行控制,LlamaIndex 通过整合和调度完成最终任务。 大模型的一个最大特点就是无法保证回答百分…

假如有一个嵌套集合,怎么通过stream流将集合放到一个集合之中?

假如有一个嵌套集合,怎么通过stream流将集合放到一个集合之中? 问题解释:你有一个嵌套的集合,想要通过 Stream 流的方式将其中嵌套的集合放到一个新的集合中。可以使用 flatMap 方法来实现。这种方法非常适合处理嵌套集合的情况。…

2个方法教你如何删除ZIP压缩包密码

zip压缩包设置了加密密码,每次解压文件都需要输入密码才能够顺利解压出文件,当压缩包文件不再需要加密的时候,大家肯定想删除压缩包密码,或是忘记了压缩包密码,想要通过删除操作将压缩包密码删除,就能够顺利…

Basic Pentesting:2-打靶渗透【附代码】(权限提升)

靶机下载地址: https://www.vulnhub.com/entry/basic-pentesting-2,241/https://www.vulnhub.com/entry/basic-pentesting-2,241/ 1. 主机发现端口扫描目录扫描敏感信息获取 1.1. 主机发现 nmap -sn 192.168.7.0/24|grep -B 2 08:00:27:1D:4A:27 1.2. 端口扫描 …

MongoDB学习记录

1、初识Mongo 概述:与关系型数据库不同,MongoDB 的数据以类似于 JSON 格式的二进制文档存储,通常称这种格式为Bson,Bson不仅支持JSON中已有的数据类型,还增加了一些额外的数据类型,例如日期和二进制数据&a…