从零学Java 线程安全的集合

线程安全的集合

文章目录

  • 线程安全的集合
    • 1 List 和 Set体系
      • Collections中的工具方法
      • 1.1 CopyOnWriteArrayList
      • 1.2 CopyOnWriteArraySet
      • 1.3 ConcurrentHashMap
    • 2 CAS算法
    • 3 Queue接口(队列)
      • 3.1 ConcurrentLinkedQueue
      • 3.2 BlockingQueue接口(阻塞队列)

Collection体系集合、以及线程安全集合。

在这里插入图片描述

注:下划线代表线程安全集合

1 List 和 Set体系

Collections中的工具方法

Collections工具类中提供了多个可以获得线程安全集合的方法。

  • public static Collection synchronizedCollection(Collection c)
  • public static List synchronizedList(List list)
  • public static Set synchronizedSet(Set s)
  • public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
  • public static SortedSet synchronizedSortedSet(SortedSet s)
  • public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)

JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchonized实现。

1.1 CopyOnWriteArrayList

  • 线程安全的ArrayList,加强版读写分离。
  • 写有锁,读无锁,读写之间不阻塞,优于读写锁。
  • 写入时,先copy一个容器副本、再添加新元素,最后替换引用。
  • 使用方式与ArrayList无异。

1.2 CopyOnWriteArraySet

  • 线程安全的Set,底层使用CopyOnWriteArrayList实现。
  • 唯一不同在于,使用addIfAbsent()添加元素,会遍历数组
  • 如存在元素,则不添加(扔掉副本)。

1.3 ConcurrentHashMap

JDK 1.7

  • 初始容量默认为16段(Segment),使用分段锁设计。
  • 不对整个Map加锁,而是为每个Segment加锁。
  • 当多个对象存入同一个Segment时,才需要互斥。
  • 最理想状态为16个对象分别存入16个Segment,并行数量16。
  • 使用方式与HashMap无异。

JDK 1.8

  • 改为CAS无锁算法。

eg:

public class TestThreadSafe {public static void main(String[] args) {//ArrayList<String> list=new ArrayList<>();//CopyOnWriteArrayList list=new CopyOnWriteArrayList();//CopyOnWriteArraySet set=new CopyOnWriteArraySet();ConcurrentHashMap<String,String> hashMap=new ConcurrentHashMap<>();ExecutorService es = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) {es.submit(new Runnable() {@Overridepublic void run() {for (int j = 0; j < 10; j++) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}hashMap.put(Thread.currentThread().getName()+"..."+j,"xxx");}}});}es.shutdown();while(!es.isTerminated());System.out.println("元素个数:"+hashMap.size());}
}

2 CAS算法

CAS:Compare And Swap(比较交换算法)

  • 其实现方式是基于硬件平台的汇编指令,是靠硬件来实现的,效率高。
  • 并且比较和交换过程是同步的。
  • CAS是一种乐观锁。

乐观锁:

  • 总是认为是线程安全,不怕别的线程修改变量,如果修改了再重新尝试,直到成功。
  • CAS是乐观锁。

悲观锁:

  • 总是认为线程不安全,不管什么情况都进行加锁,要是获取锁失败,就阻塞。
  • synchronized、ReentrantLock是悲观锁。

CAS比较交换算法,修改的方法包含三个核心参数(V,E,N)

  • V:要更新的变量、E:预期值、N:新值。
  • 只有当V==E时,V=N;否则表示已被更新过,则取消当前操作,继续判断直到成功。

eg:

使用代码模拟CAS算法

public class TestCAS {public static void main(String[] args) {Cas cas=new Cas();ExecutorService es = Executors.newFixedThreadPool(100);for (int i = 0; i < 100; i++) {es.submit(() -> {while(true) {int old = cas.getV();boolean b = cas.compareAndSwap(old, new Random().nextInt(100));System.out.println(Thread.currentThread().getName()+"..."+b);if(b){break;}}});}es.shutdown();}static class Cas{private int V;//更新的变量//获取V的值public int getV(){return V;}public synchronized boolean compareAndSwap(int E,int N){if(E==V){V=N;return true;}return false;}}
}

3 Queue接口(队列)

Collection的子接口,表示队列FIFO(First In First Out)

常用方法:

  • 抛出异常:
    • boolean add(E e) //顺序添加一个元素(到达上限后,再添加则会抛出异常)
    • E remove() //获得第一个元素并移除(如果队列没有元素时,则抛异常)
    • E element() //获得第一个元素但不移除(如果队列没有元素时,则抛异常)
  • 返回特殊值:推荐使用
    • boolean offer(E e) //顺序添加一个元素 (到达上限后,再添加则会返回false)
    • E poll() //获得第一个元素并移除 (如果队列没有元素时,则返回null)
    • E peek() //获得第一个元素但不移除 (如果队列没有元素时,则返回null)

3.1 ConcurrentLinkedQueue

线程安全、可高效读写的队列,高并发下性能最好的队列。

  • 采用CAS比较交换算法

eg:

public class TestQueue {public static void main(String[] args) {
//        Queue<String> queue=new LinkedList<>();Queue<String> queue=new ConcurrentLinkedQueue<>();//入队
//        queue.offer("aaa");
//        queue.offer("bbb");
//        queue.offer("ccc");ExecutorService es = Executors.newFixedThreadPool(3);for (int i = 0; i < 3; i++) {es.submit(new Runnable() {@Overridepublic void run() {queue.offer(Thread.currentThread().getName());}});}//出队es.shutdown();while(!es.isTerminated());int count=queue.size();for (int i = 0; i < count; i++) {System.out.println(queue.poll());}}
}

3.2 BlockingQueue接口(阻塞队列)

Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法。

方法:

  • void put(E e) //将指定元素插入此队列中,如果没有可用空间,则等待。
  • E take() //获取并移除此队列头部元素,如果没有可用元素,则等待。
  • 可用于解决生产者、消费者问题。

实现类:

  • ArrayBlockingQueue:数组结构实现,有界队列。(手工固定上限)
  • LinkedBlockingQueue:链表结构实现,有界队列。(默认上限Integer.MAX_VALUE)

eg:

package StageOne.day21.demo02;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/16 14:32*/
public class TestBlockingQueue {public static void main(String[] args) {//创建阻塞队列BlockingQueue<String> queue = new LinkedBlockingQueue<>(6);//创建线程池ExecutorService es = Executors.newCachedThreadPool();//提交任务es.submit(()->{for (int i = 0; i < 30; i++) {try {queue.put("面包"+i);System.out.println("生产了"+i);} catch (InterruptedException e) {throw new RuntimeException(e);}}});es.submit(()->{for (int i = 0; i < 30; i++) {try {String take = queue.take();System.out.println("消费了"+take);} catch (InterruptedException e) {throw new RuntimeException(e);}}});es.shutdown();}
}

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

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

相关文章

PyTorch Tutorial 2.0

这里是对于PyTorch Tutorial-CSDN博客的补充&#xff0c;但是与其相关的NLP内容无关&#xff0c;只是一些基础的PyTorch用法的记录&#xff0c;主要目的是能够自己生成一些模拟的数据集。先介绍随机数的目的是因为based on随机数方法。 当然在看随机数的方法的时候&#xff0c…

【开源】基于JAVA语言的固始鹅块销售系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固始鹅块模块2.4 鹅块订单模块2.5 评论管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 鹅块类型表3.2.2 鹅块表3.2.3 鹅块订单表3.2.4 鹅块评论表 四、系统展示五、核心代码5.…

解决com.alibaba.fastjson.JSONException: default constructor not found的问题

1.问题描述 在进行JSON和对象互转时&#xff0c;发现有个报错&#xff1a; com.alibaba.fastjson.JSONException: default constructor not found. class com.hellobike.ph.match.service.taxi.model.message.DelayAddSkuMsg 2.原因和解决方案 通过其提示可以看出在利用fastJ…

Vue组件之间的通信方式都有哪些?

面试官&#xff1a;Vue组件之间的通信方式都有哪些&#xff1f; 一、组件间通信的概念 开始之前&#xff0c;我们把组件间通信这个词进行拆分 组件通信 都知道组件是vue最强大的功能之一&#xff0c;vue中每一个.vue我们都可以视之为一个组件通信指的是发送者通过某种媒体以…

详解toLowerCase(判断字符串相等)

一、toLowerCase 函数简介 toLowerCase() 是一个在多个编程语言中都存在的字符串方法&#xff0c;它的作用是将字符串中的所有大写字母转换为对应的小写字母。 常用于文本处理、搜索和比较等情况&#xff0c;以确保字符串的一致性和非大小写敏感的操作。 二、判断字符串相等 下…

Vim一键配置指南,打造高效率C++开发环境

文章目录 前言安装与卸载功能演示gcc/g升级问题 前言 Vim作为当下最受欢迎的文本编译器之一&#xff0c;不仅具有强大的文本编辑功能&#xff0c;还提供了高度的可定制性。用户可以根据自己的喜好自定义配置&#xff0c;并且通过自己编写插件或者使用现有的插件来扩展Vim的功能…

【STM32】STM32学习笔记-I2C通信外设(34)

00. 目录 文章目录 00. 目录01. I2C简介02. I2C外设简介03. I2C框图04. I2C基本结构05. 主机发送06. 主机接收07. 软件/硬件波形对比08. 预留09. 附录 01. I2C简介 I2C(Inter&#xff0d;Integrated Circuit)总线是一种由NXP&#xff08;原PHILIPS&#xff09;公司开发的两线式…

黑马程序员——javase基础——day02——运算符选择语句

目录&#xff1a; 运算符 算术运算符案例数值拆分操作的三种情况 数字相加(类型转换)字符相加字符串相加赋值运算符选择语句 顺序结构Debug的基本使用选择语句之if if语句格式1if语句格式2和格式3案例1(交通信号灯)关系运算符案例2(奇偶数)案例3(手机以旧换新)案例4(你是青年人…

OpenCV-Python(42):摄像机标定

目标 学习摄像机畸变以及摄像机的内部参数和外部参数根据摄像机相关参数对畸变图像进行修复 基础说明 今天的低价单孔摄像机(照相机)会给图像带来很多畸变。畸变主要有两种:径向畸变和切向畸变。如下图所示用红色直线将棋盘的两个边标注出来&#xff0c;但是你会发现棋盘的边…

小程序样例1:简单待办列表

基本功能&#xff1a; 显示所有待办列表&#xff08;点击不同的文本进行显示&#xff09; 没完成的待办 已完成的待办 新建待办test 清除待办foo 代码js文件&#xff1a; //index.js //获取应用实例 const app getApp(); Page({data: {todo: ,todos: [{"id": 1474…

NanoPi NEO Air 配置指南

近期淘了块非常小巧的开发板 NaoPi NEO Air&#xff0c;这块板子仅有 40mm x 40mm 大小&#xff0c;除了一个 MicroUSB OTG 接口外如果想要扩展USB口就得使用左侧排针增加USB接口了。 关于 NanoPi NEO Air NanoPi NEO Air是一款基于全志H3四核A7主控的开源无线创客板&#xff…

SDRAM小项目——命令解析模块

简单介绍&#xff1a; 在FPGA中实现命令解析模块&#xff0c;命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令&#xff0c;虽然代码不多&#xff0c;但是却十分重要。 SDRAM的整体结构如下&#xff0c;可以看出&#xff0c;命令解析模块cmd_decode负责…

springcloud-cloud provider-payment8001微服务提供者支付Module模块

文章目录 IDEA新建project工作空间cloud-provider-payment8001微服务提供者支付Module模块建表SQL测试 IDEA新建project工作空间 微服务cloud整体聚合父工程Project 写pom文件 <?xml version"1.0" encoding"UTF-8"?><project xmlns"htt…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-9 可观测性与分离原理

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-9 可观测性与分离原理

vue知识-07

ref # 放在组件上&#xff1a; this.$refs.名字 ---组件对象.组件对象.属性 # 在vue项目中使用: // 写在组件上 <HelloWorld ref"my_hello_world"></HelloWorld>handleClick() {console.log(this.$refs)this.$refs.my_hello_world.name # 获取子组件中…

vue:使用【3.0】:条件模块

一、条件层级效果图 二、代码 <template><ContentWrap><!-- 添加条件分支:level1 --><div class"btnBox" v-if"isEdit"><el-button type"primary" click"add">添加条件分支</el-button></div…

UE5 RPG AttributeSet的设置

AttributeSet 负责定义和持有属性并且管理属性的变化。开发者可以子类化UAttributeSet。在OwnerActor的构造方法中创建的AttributeSet将会自动注册到ASC。这一步必须在C中完成。 Attributes 是由 FGameplayAttributeData定义的浮点值。 Attributes能够表达从角色的生命值到角色…

《现代C++语言核心特性解析》笔记草稿

仅供学习记录之用&#xff0c;谢绝转发 第1章 新基础类型&#xff08;C11&#xff5e;C20&#xff09; 1.1 整数类型long long 更多笔记 “在C中应该尽量少使用宏&#xff0c;用模板取而代之是明智的选择。C标准中对标准库头文件做了扩展&#xff0c;特化了long long和unsi…

【C++】vector的使用及模拟实现

目录 一、vector的介绍及使用1.1 介绍vector1.2 vector的使用1.2.1 构造1.2.2 遍历访问1.2.3 容量空间1.2.4 增删查改 二、vector的模拟实现2.1 成员变量2.2 迭代器相关函数2.3 构造-析构-赋值重载2.3.1 无参构造2.3.2 有参构造12.3.3 有参构造22.3.4 拷贝构造2.3.5 赋值重载2.…

RAG基础功能优化、以及RAG架构优化

RAG基础功能优化 对RAG的基础功能优化&#xff0c;我们要从RAG的流程入手[1]&#xff0c;可以在每个阶段做相应的场景优化。 从RAG的工作流程看&#xff0c;能优化的模块有&#xff1a;文档块切分、文本嵌入模型、提示工程优化、大模型迭代。下面针对每个模块分别做说明&#…