从零学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.…

Spring Boot整合Junit

1.Junit启动器&#xff0c;配置pox.xml <!--junit启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency> 2.编写业务代码 2.1dao package com.zh…

计算机网络(第六版)复习提纲2

二、物理层 2.1 物理层基本概念 物理层协议常常成为物理层规程 物理层的主要任务为确定与传输媒体的接口有关的一些特性&#xff1a; 1.机械特性&#xff1a;指明接口所用接线器的尺寸等&#xff1b; 2.电气特性&#xff1a;指明接口电缆各条线上的电压范围&#xff1b; 3.功能…

解决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我们都可以视之为一个组件通信指的是发送者通过某种媒体以…

top命令详解

top命令经常用来监控linux的系统状况&#xff0c;是常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用情况。 top的使用方式 top [-d number] 或 top [-bnp] 参数解释&#xff1a; -d&#xff1a;number代表秒数&#xff0c;表示top命令显示的页面更新一…

类的加载机制

什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象&#xf…

【征服redis4】一文征服redis的Lettuce客户端

前面我们介绍了jedis客户端的使用&#xff0c;本文我们继续介绍第二个常用的客户端Lettuce。与jedis相比Lettuce有什么特征和区别&#xff0c;以及使用的时候有哪些重要的问题呢&#xff1f;本文我们一起来探究一下。 1. Lettuce介绍与安装测试 1.1. 什么是Lettuce Lettuce是…

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

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

(202401)深度强化学习基础与实践1:马尔科夫过程、DNQ算法回顾

文章目录 序言马尔科夫决策过程含义性质回报状态转移矩阵 DQN算法深度网络经验回放目标网络实战DQN算法 DQN 算法进阶Double DQNDueling DQNNoisy DQNPER DQNC51 算法 序言 本文章记录Datawhale开源学习组织2024年第一期学习&#xff0c;《深度强化学习基础与实践》第二期的任…

金属由液体凝固成液体,由于液体凝固为固体时,体积会缩小,导致金属铸造不可避免出现缩孔现象吗?

问题描述&#xff1a;金属由液体凝固成液体&#xff0c;由于液体凝固为固体时&#xff0c;体积会缩小&#xff0c;导致金属铸造不可避免出现缩孔现象吗&#xff1f; 问题解答&#xff1a; 在金属铸造过程中&#xff0c;确实存在由于液态金属凝固成为固态时体积收缩而导致缩孔…

mysql Linux系统云服务器配置远程访问

mysql Linux系统云服务器配置远程访问 1.安装mysql 服务器 2.配置远程登录用户权限 3.进行远程登录&#xff0c;并访问数据库 1.安装mysql 服务器 首先先安装一下云服务器 sudo apt-get install mysql-server安装好之后&#xff0c;我们直接以root用户登录&#xff1a; …

java set集合和list集合的区别

Java 中的 Set 集合和 List 集合都是用于存储一组元素的容器&#xff0c;但它们之间存在一些重要的区别。 元素唯一性&#xff1a;Set 集合中的元素是唯一的&#xff0c;不允许重复。而 List 集合中的元素可以重复。元素顺序&#xff1a;List 集合中的元素保持了它们被添加的顺…

大学生应该优先学技术还是准备考研

最近看到过不少人问这个问题&#xff0c;说实话哪一个优先级更高其实是要根据不同行业具体分析的&#xff0c;例如医药或者师范这类文凭跟工资直接挂钩的行业自然是考研优先级要高一些&#xff0c;但是CSDN这边的用户应该是计算机之类的技术专业较多&#xff0c;一般这种工作更…

EXEC sp_addlinkedserver 指定服务器ip

要使用 sp_addlinkedserver 存储过程在 SQL Server 中指定服务器 IP 地址&#xff0c;你可以在 datasrc 参数中提供服务器 IP 地址。以下是一个示例&#xff1a; EXEC sp_addlinkedserver server LinkToServer2, provider SQLNCLI, datasrc 192.168.0.1, -- 这里是目标服务器…

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(你是青年人…

The Parade

Berland军队正在为一场大型阅兵式做准备。已经决定&#xff0c;参与其中的士兵将被分为k行&#xff0c;所有行都将包含相同数量的士兵。 当然&#xff0c;并不是每一次把士兵排成k排都是合适的。同一排中所有士兵的身高差异不应超过1。每个士兵的身高是一个介于1和n之间的整数。…