Java如何保证集合是线程安全的?(代码实践抛砖引玉)

2023-11-10

在Java中绝大部分的集合像什么ArrayList、HashMap等绝大部分不是线程安全的。仅有的线程安全的实现,像HashTable、Vector等在性能上又不好。但是不要怕啊。我们大Java还有并发包(Java.util.concurrent)啊,为高度并发需求提供了全面安全的支持。

一、在传统的集合框架中,如何解决线程安全问题。

当然,除了Hashtable等同步容器,我们可以使用同步包装器创建一个线程安全的容器。但是这种方式用的是非常粗的同步方式,在高并发情况下,性能比较低下。

具体的位置如下

在这里插入图片描述

下面楼主写了有一些实践的代码:

package com.newframe.controllers.api;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.SynchronousQueue;

/**
 * 测试传统线程安全的集合类
 */
public class TestTraditionSyn {

    public static void main(String[] args) {

        /**
         * 1。在传统的集合框架中。
         * 除了Hashtable这个是线程安全的同步容器。
         * 他的实现基本上就是将Put、get、size等各种
         * 方法的操作加上"synchronized"。这就导致了所有的并发操作都在竞争同一把锁
         * 一个线程在进行同步操作时,其他线程只能等待,大大降低了并发执行的效率
         * (当然这个因为同步的线程开销较大,不推荐使用)
         * 还可以通过调用Collections工具类提供的包装类。来构造线程安全的同步包装容器,如下所示
         */
        //构造一个线程安全的List
        List<String> list = Collections.synchronizedList(new ArrayList<>());
        list.add("hello");
        list.add("world");

        Iterator iterator1 = list.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }

        //构造一个线程安全的Map
        Map<String,Object> map1 = Collections.synchronizedMap(new HashMap<>());
        map1.put("1","wang");
        map1.put("2","dong");

        map1.forEach((key,value) ->{
            System.out.println("map1:" + key + "," + value);
        });
    }
}

二、重头戏首选的肯定还是我们的Java并发包啊

具体位置如下:

在这里插入图片描述

下面楼主也写了一些示范如何使用的简单代码:

package com.newframe.controllers.api;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.SynchronousQueue;

/**
 * 测试并发包中的集合类
 */
public class TestConcurrentSyn {

    public static void main(String[] args) {

        /**
         * 2。并发包。在工作中,我们更加普遍的是选择利用并发包提供
         * 适合在高度并发的环境下使用
         * 线程安全容器类
         * 这个只要你是按照并发包的标准创建的集合,都是线程安全的。
         */
        //关于map的ConcurrentHashMap
        ConcurrentHashMap<String,Object> map2 = new ConcurrentHashMap<>();
        map2.put("1","我是并发包直接构建的");
        map2.put("2","我是线程安全的Map容器,ConcurrentHashMap");
        map2.forEach((key,value) ->{
            System.out.println("map2:" + key + "," + value);
        });

        //关于list的CopyOnWriteArrayList
        CopyOnWriteArrayList<Integer> list2 = new CopyOnWriteArrayList<>();
        list2.add(67612);
        list2.add(67362);
        list2.forEach(list ->{
            System.out.println(list);
        });

        /**
         * 并发包中的线程安全队列
         */
        //ArrayBlockingQueue
        ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue(10);
        arrayBlockingQueue.add("1");
        arrayBlockingQueue.add("3");
        arrayBlockingQueue.forEach(queue->{
            System.out.println(queue);
        });
    }
}

三、关于Java8以后的ConcurrentHashMap的一点思考。

ConcurrentHashMap的设计实现是一直都在不断的演化,性能也是在不断的提高。

早期的ConcurrentHashMap,其实现主要是基于:

  • 分离锁。在内部进行分段(Segment),里面则是HashEntry的数组,和HashMap类似,哈希相同的条目也是以链表的形式存放。
  • HashEntry内部使用volatile的value字段来保证可见性。

那么在Java8中,这个有什么变化呢?

  • 在结构上,虽然仍然有Segment定义,但是仅仅是为了给旧版本兼容。初始化已经改成了Lazy-load的形式了,有效避免了初始化开销。
  • 数据存储利用的是Volatile来保证可见性。如下图:

在这里插入图片描述

好啦,关于这个里面的东西太多了,还需要深入研究,当然,在工作中如果能明确应用场景,做出正确的选择才是关键。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java如何保证集合是线程安全的?(代码实践抛砖引玉) 的相关文章

  • 为什么Java中的Set数据结构内部使用Map?

    我想知道为什么HashSet http www docjar com html api java util HashSet java html uses HashMap TreeSet uses TreeMap and LinkedHash
  • 如何对 HashMap 键进行排序[重复]

    这个问题在这里已经有答案了 我有一个问题 HashMap
  • Hashmap 单键保存一个类。计算密钥并检索计数器

    我正在开发一个数据库自我项目 我有一个来自以下位置的输入文件 http ir dcs gla ac uk resources test collections cran http ir dcs gla ac uk resources tes
  • Java中如何从HashMap中获取对象

    我试图在给定密钥时从 HashMap 获取测试对象的速度 但我不太确定该怎么做 我尝试过这种方式 但它是错误的 hash values getSpeed 有什么帮助吗 谢谢 class Test private String id priv
  • Ruby - 将数组映射到哈希图

    我有一个数组和一个返回给定值的函数 最终我想创建一个哈希映射 将数组的值作为键值 将 f key value 的结果作为值 是否有一种干净 简单的方法 例如类似于数组的each map 使用块来执行此操作 所以相当于 hsh 1 2 3 4
  • java hashmaps 的 get() 函数

    我声明了以下哈希图 HashMap
  • Java HashMap - 深拷贝

    我只是想找出如何进行深层复制的最佳解决方案HashMap 该映射中没有对象实现Cloneable 我想找到比序列化和反序列化更好的解决方案 看一眼深度克隆 在 Google Code 上您可以找到一个库 你可以阅读它https github
  • Java 中的 ConcurrentHashMap 和 Hashtable [重复]

    这个问题在这里已经有答案了 Java 中的 ConcurrentHashMap 和 Hashtable 有什么区别 哪个对于线程应用程序更有效 ConcurrentHashMap 和 Hashtable 锁定机制 Hashtable属于Co
  • 同步不经常更新的哈希图的最佳方式

    我有一个在应用程序中使用的 HashMap 数据是在应用程序初始加载期间从数据库填充的 然后它始终只是读取并且从不更新 会有多个线程不断地读取数据 由于数据永远不会更新 因此我们目前不使用任何同步 仅使用 HashMap 我们现在定义的方式
  • Java 弱哈希映射 - 需要根据值的弱点而不是键来删除条目

    所以JavaWeakHashMap让我们创建一个映射 如果其键变弱 则删除该映射的条目 但是我怎样才能创建一个Map 当它的条目被删除时values地图上变弱了 我想使用映射的原因是作为全局哈希表 它根据对象的 ID 跟踪对象 ID gt
  • 对 Python 中的嵌套字典进行排序

    我有以下字典 var a Black grams 1906 price 2 05 Blue grams 9526 price 22 88 Gold grams 194 price 8 24 Magenta grams 6035 price
  • 在哈希图中存储字符和二进制数

    我正在尝试存储字母到二进制数的映射 这是我的映射 h 001 i 010 k 011 l 100 r 101 s 110 t 111 为此 我创建了一个哈希映射并存储了键值对 我现在想显示给定句子的相应二进制值 这是我的代码 package
  • 哈希表的空间复杂度是多少?

    具有 32 位键和指向单独存储的值的 32 位指针的哈希表的大小是多少 是 2 32 个槽 4 字节 键 4 字节 指向值的指针 4 10 9 4 4 32GB 我想了解哈希表的空间复杂度 我认为你问错了问题 数据结构的空间复杂度表示它占用
  • Java中HashMap和ArrayList的区别?

    在爪哇 ArrayList and HashMap被用作集合 但我不明白我们应该在哪些情况下使用ArrayList以及使用时间HashMap 他们两者之间的主要区别是什么 您具体询问的是 ArrayList 和 HashMap 但我认为要完
  • 从 arraylist 和 hashmap 中删除重复项

    我有一个数组列表 其中包含付款人的姓名 另一个数组列表包含每次付款的费用 例如 nameArray 尼古拉 劳尔 洛伦佐 劳尔 劳尔 洛伦佐 尼古拉 价格数组 24 12 22 18 5 8 1 我需要将每个人的费用相加 所以数组必须变成
  • Python 中的哈希映射

    我想用Python实现HashMap 我想请求用户输入 根据他的输入 我从 HashMap 中检索一些信息 如果用户输入HashMap的某个键 我想检索相应的值 如何在 Python 中实现此功能 HashMap
  • JQuery $.ajax() 在 java servlet 中发布数据

    我想将数据发送到 java servlet 进行处理 数据将具有可变长度并采用键 值对 A1984 1 A9873 5 A1674 2 A8724 1 A3574 3 A1165 5 数据不需要这样格式化 这就是我现在的方式 var sav
  • 使用 HashMap 映射 String 和 int

    我有一个显示国家 地区名称的列表视图 我已将名称作为字符串数组存储在 strings xml 中 称为国家 地区名称 在填充 ListView 时 我使用从 strings xml 读取的 ArrayAdapter String count
  • 哈希表到 Lwuit 表

    Hashtable iHashtable new Hashtable iHashtable put Name Jhon iHashtable put Address India Enumeration iEnumeration iHasht
  • 如果计算的哈希码超过整数最大限制,会发生什么?

    这是 Java HashTable 类的 hashCode 实现 如果哈希表中的元素数量很大并且哈希码超过 INTEGER MAX LIMIT 2 147 483 648 到 2 147 483 647 该怎么办 我假设 hashCodes

随机推荐

  • 已获万赞,最新Android通用流行框架大全

    前言 2021全年从开头到结尾似乎就没多少好消息 这里我说的是整个互联网行业 并没有单单挑出某个公司或者某个细分领域 而对于广大Android开发者来说 找工作似乎也变得越来越难了 2021年1月 我在51job搜索了一下北京地区的Andr
  • 基于STM32 的IIC 模拟主机编写

    最近在学习STM32 的IIC IO 模拟主机方式 好像失败了 include myiic h include delay h MCU VERSION DATA 作者 other Function IIC
  • 吴恩达深度学习笔记五:卷积神经网络 人脸识别和风格迁移部分

    1 人脸识别 人脸验证 Face Verification 输入图片和模板图片是否为同一人 一对一问题 人脸识别 Face Recognition 输入图片 检测是否为多个模板图片中的一个 一对多问题 一般来说 人脸验证由于范围较小难度较小
  • MyBatis实现乐观锁和悲观锁

    使用mysql做数据库 mybatis做orm的系统中 mybatis的乐观锁和悲观锁实际上就是mysql的乐观锁和悲观锁 实例中使用springboot整合mybatis 一并记录了 添加依赖
  • 【数据压缩】LZW编解码原理及算法实现

    一 LZW简介 LZW压缩 LZW compression 是一种由Abraham Lempel Jacob Ziv和Terry Welch发明的基于表查寻算法把文件压缩成小文件的无损压缩方法 LZW算法又叫 串表压缩算法 就是通过建立一个
  • 计算机毕业论文选题 - 毕设选题推荐

    文章目录 0 前言 1 java web 管理系统 毕设选题 2 java web 平台 业务系统 毕设选题 3 游戏设计 动画设计类 毕设选题 适合数媒的同学 4 算法开发 5 数据挖掘 毕设选题 6 大数据处理 云计算 区块链 毕设选题
  • npm 常用的命令

    目录 npm是什么 npm install 安装模块 npm uninstall 卸载模块 npm update 更新模块 npm outdated 检测模块是否过时 npm ls 查看安装的模块 npm init 初始化package j
  • Ubuntu +ros 的node的详解

    1 rosrun turtlesim turtlesim node 启用一个新的节点 2 rosnode list 就会发现一个新的节点 3 rosnode info turtlesim 查看节点的相关信息 4 就会看到发布者 以及相应的主
  • 原生js本地存储?看这一篇就够了!!!

    JS cookie 1 概述 cookie也叫HTTP Cookie 最初是客户端与服务器端进行会话 Session 使用的 如果没写expires 那么下次打开网页 cookie就会消失 这个就是会话机制 2 格式 name value
  • C++中基类和派生类之间的转换实例

    本文实例讲解了C 中基类和派生类之间的转换 对于深入理解C 面向对象程序设计有一定的帮助作用 此处需要注意 本文实例讲解内容的前提是派生类继承基类的方式是公有继承 关键字public 具体分析如下 以下程序为讲解示例 1 2 3 4 5 6
  • OSG学习笔记22——设置物体透明,再恢复

    设置物体透明 trans是透明度的设置 这里如果没有setRenderingHint 虽然看起来是透明的 但模型还是会遮挡其他模型 然后就是BLEND要打开 光照和深度测试要关掉 模型的材质也要事先设置 并将材质保存起来以便恢复的时候调用
  • 虚拟机磁盘挂载和扩容

    磁盘挂载 查看磁盘状态 lsblk 格式化磁盘 主意上一步查看的磁盘格式 下面以ext4为例 mkfs ext4 dev vdb 挂载磁盘 mount dev vdb root 修改文件 vi etc fstab 在最后一行加上 dev v
  • 命令行发送UDP

    https www cnblogs com Dennis mi articles 6866762 html 如果往本地UDP端口發送數據 那麼可以使用以下命令 echo hello gt dev udp 192 168 1 81 5060
  • linux 7 虚拟机安装,CentOS 7上使用virt-manager安装虚拟机

    KVM Kernel based Virtual Machine 是基于x86架构上Linux操作系统的全虚拟化解决方案 在CentOS7中 KVM已经被集成到内核中 相当于使用内核来做虚拟机管理程序 由于KVM本身就工作内核环境中 所以执
  • arthas常用命令整理

    官网链接 Arthas Install Arthas 3 5 4 文档Arthas Install Arthas 3 5 4 文档 今天是1024程序员节 昨天研究了下arthas整理一下笔记 常用命令 watch watch Arthas
  • 上传jar包到nexus私有仓库

    通常在项目开发过程中 免不了需要上传公共组件包到nexus私有仓库 尽管前期有专人来搭建nexus私有仓库并上传好公共组件包 但后期免不了会自研一些组件包要自己上传 本篇文章就针对命令上传jar包到nexus私服仓库中心做个简单记录 便于后
  • 写需求套路/组件使用套路

    写需求套路 1 html css 2 数据铺设 数据绑定 数据微调 3 js交互 gt 事件 正则 组件使用套路 1 找组件 引组件 2 用组件 标签和js复制 读 删 改
  • python实现opencv学习四:numpy操作数组输出图片

    读取一张图片 并将像素取反 代码 coding GBK import cv2 as cv def access pixles image print image shape height image shape 0 width image
  • 处理el-table大数据卡顿的问题,包含tree型数据格式

    文章目录 概要 技术细节 小结 概要 如果你有更丰富的表格需求 可以查看我另一篇文章 关于vxe table的使用心得及扩展 1 现象 有时候el table的数据可能有成千上万条 而且又要在一页显示完 这时候页面渲染的dom太多了 可能会
  • Java如何保证集合是线程安全的?(代码实践抛砖引玉)

    在Java中绝大部分的集合像什么ArrayList HashMap等绝大部分不是线程安全的 仅有的线程安全的实现 像HashTable Vector等在性能上又不好 但是不要怕啊 我们大Java还有并发包 Java util concurr