Java里的并发容器与安全共享策略总结
一、并发容器
ArrayList --> CopyOnWriteArrayList
概念 : 简单的讲就是写操作时赋值,当有新元素添加到CopyOnWriteArrayList时,它先从原有的数组里边Copy一份出来然后在新的数组上做些操作,操作完成以后在将引用指向新的数组;CopyOnWriteArrayList所有的操作都是在锁的保护下进行的,这样做的目的主要是为了在多线程并发做add操作的时候复制出多个副本出来导致数据混乱;
缺点 :
① 由于是copy的操作所以比较消耗内存,如果元素的内容较多的时候可能会触发GC,
② 不能用于实时读的场景,它比较适合读多写少的场景;
思想 :
① 读写分离;
② 最终一致性;
③ 另外开辟空间解决并发冲突;
// CopyOnWriteArrayList @Slf4j @ThreadSafe public class CopyOnWriteArrayListExample {// 请求总数public static int clientTotal = 5000;// 同时并发执行的线程数public static int threadTotal = 200;private static List<Integer> list = new CopyOnWriteArrayList<>();public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(threadTotal);final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);for (int i = 0; i < clientTotal; i++) {final int count = i;executorService.execute(() -> {try {semaphore.acquire();update(count);semaphore.release();} catch (Exception e) {log.error("exception", e);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();log.info("size:{}", list.size());}private static void update(int i) {list.add(i);} }
HashSet --> CopyOnWriteArraySet 与 TreeSet --> ConcurrentSkipListSet
概念 :
CopyOnWriteArraySet它是线程安全,底层实现是使用CopyOnWriteArrayList,它的很多特性都与CopyOnWriteArrayList相似包括适用场景;
ConcurrentSkipListSet是jdk6新增的类,支持自然排序,可以在构造的时候自己定义比较器,它是基于Map集合的,在多线程环境下ConcurrentSkipListSet它里边的remote add 等方法都是线程安全的,但是对于批量操作并不能保证以原子方式进行操作,在批量操作的时候只能保证每一次的操作是原子性的;ConcurrentSkipListSet在使用批量操作的时候可能需要手动处理一下;
// CopyOnWriteArraySet @Slf4j @ThreadSafe public class CopyOnWriteArraySetExample {// 请求总数public static int clientTotal = 5000;// 同时并发执行的线程数public static int threadTotal = 200;private static Set<Integer> set = new CopyOnWriteArraySet<>();public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(threadTotal);final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);for (int i = 0; i < clientTotal; i++) {final int count = i;executorService.execute(() -> {try {semaphore.acquire();update(count);semaphore.release();} catch (Exception e) {log.error("exception", e);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();log.info("size:{}", set.size());}private static void update(int i) {set.add(i);} }
// ConcurrentSkipListSet @Slf4j @ThreadSafe public class ConcurrentSkipListSetExample {// 请求总数public static int clientTotal = 5000;// 同时并发执行的线程数public static int threadTotal = 200;private static Set<Integer> set = new ConcurrentSkipListSet<>();public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(threadTotal);final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);for (int i = 0; i < clientTotal; i++) {final int count = i;executorService.execute(() -> {try {semaphore.acquire();update(count);semaphore.release();} catch (Exception e) {log.error("exception", e);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();log.info("size:{}", set.size());}private static void update(int i) {set.add(i);} }
HashMap --> ConcurrentHashMap 与 TreeMap --> ConcurrentSkipListMap
概念 :
ConcurrentHashMap是HashMap线程安全的版本,ConcurrentHashMap不允许空值,在实际的应用中除了少数的插入操作和删除操作外,绝大多数操作都是读取操作,而且读操作大多数都是成功的,基于这个前提ConcurrentHashMap针对读操作多了特别多的优化,具有特别高的并发性;
ConcurrentSkipListMap是TreeMap线程安全的版本,ConcurrentSkipListMap底层是使用SkipList这种跳表的结构实现的;
// ConcurrentHashMap @Slf4j @ThreadSafe public class ConcurrentHashMapExample {// 请求总数public static int clientTotal = 5000;// 同时并发执行的线程数public static int threadTotal = 200;private static Map<Integer, Integer> map = new ConcurrentHashMap<>();public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(threadTotal);final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);for (int i = 0; i < clientTotal; i++) {final int count = i;executorService.execute(() -> {try {semaphore.acquire();update(count);semaphore.release();} catch (Exception e) {log.error("exception", e);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();log.info("size:{}", map.size());}private static void update(int i) {map.put(i, i);} }
// ConcurrentSkipListMap @Slf4j @ThreadSafe public class ConcurrentSkipListMapExample {// 请求总数public static int clientTotal = 5000;// 同时并发执行的线程数public static int threadTotal = 200;private static Map<Integer, Integer> map = new ConcurrentSkipListMap<>();public static void main(String[] args) throws Exception {ExecutorService executorService = Executors.newCachedThreadPool();final Semaphore semaphore = new Semaphore(threadTotal);final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);for (int i = 0; i < clientTotal; i++) {final int count = i;executorService.execute(() -> {try {semaphore.acquire();update(count);semaphore.release();} catch (Exception e) {log.error("exception", e);}countDownLatch.countDown();});}countDownLatch.await();executorService.shutdown();log.info("size:{}", map.size());}private static void update(int i) {map.put(i, i);} }
二、J.U.C的实际构成
三、安全共享对象策略总结
1 线程限制 : 一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改;
2 共享只读 : 一个共享只读的对象,在没有额外同步的情况下,可以被多个线程并发访问,但是任何线程都不能修改它;
3 线程安全对象 : 一个线程安全的对象或者容器,在内部通过同步机制来保证线程安全,所以其他线程无需额外的同步就可以通过公共接口随意访问它;
4 被守护对象 : 被守护对象只能通过获取特定的锁来访问;
Java里的并发容器与安全共享策略总结相关推荐
- Java集合之并发容器
一:java中的并发容器总结 JDK提供的这些容器大部分在 java.util.concurrent 包中. ConcurrentHashMap: 线程安全的HashMap CopyOnWriteAr ...
- Java多线程之并发容器(五)
1.hashtable和vector 它们是支持并发操作的并发容器,hashtable只不过是在hashmap的基础上,所有的方法上都加上synchronized关键字,vector在ArrayLis ...
- Java 多线程 —— 常用并发容器
引言 本博客基于常用的并发容器,简单概括其基本特性和简单使用,并不涉及较深层次的原理分析和全面的场景用法. 适合对不了解并发容器的同学,工作中遇到类似的场景,能够对文中提到的并发容器留有简单印象就好. ...
- 【Java多线程】并发容器CopyOnWriteArrayList
一个不安全的List 预期输出结果为10000,但是实际运行结果为9992,是因为线程不安全,应该使用synchronized同步块 不安全代码 package cn.hanquan.test;imp ...
- java 并发queue_深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介
Queue是JDK 5以后引入的新的集合类,它属于Java Collections Framework的成员,在Collection集合中和List/Set是同一级别的接口.通常来讲Queue描述的是 ...
- Java里的容器存放的元素必须是1个对象.
我们经常看到这个句话: Java里存放的容器只能是1个对象. 一. 值类型和对象类型. 实际上, java里的变量可以分为两种类型, 一种是值类型. 一种是对象类型. 1.1 值类型变量 所谓值类型的 ...
- 聊聊并发-Java中的Copy-On-Write容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
- java高并发(十二)并发容器J.U.C
并发容器是JDK提供的一个包名:java.util.concurrent ArrayList -> CopyOnWriteArrayList CopyOnWriteArrayList是线程安全的 ...
- Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))...
转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用 1.1. ReentrantLoc ...
最新文章
- Linux下root密码忘记的解决办法
- ICA处理后,如何判断眼电、心电等成分?
- Java判断工作日计算,计算随意2个日期内的工作日
- 天题系列: Candy
- python 合并重叠数据
- MySQL创建索引跳过redo_明明我建了索引,为什么sql执行的还是这么慢?
- 计算机玩游戏不能全屏,玩游戏屏幕两边有黑条?教你简单几步轻松解决-win7玩游戏不能全屏...
- 「ruby/MiniMagick」用MiniMagick处理图片
- Unity3D之NGUI基础7:UI动态加载
- popwindow下拉筛选 二级联动_工作录入数据需要三级联动下拉菜单,Excel轻松制作!-Excel教程...
- version GLIBC_2.28 not found
- python入门教程汇总
- Oracle 常用SQL语句大全(精)
- wifi 小米pro 驱动 黑苹果_【黑果小兵】小米Pro macOS High Sierra 10.13黑苹果安装教程...
- jquery点击图片放大功能
- 版本控制工具svn和git
- python生成词云图、特殊图形_Python模块---Wordcloud生成词云图
- MySQL备份的几种常用方法与恢复步骤
- java名片_JavaWeb练习-网上名片管理系统
- GAMES101 13节 光线追踪 笔记
热门文章
- border-box
- SicilyBrackets Matching
- 浅析LAN交换机的线速释义 From: www.c114.net
- wgs-84,gcj-02,bd-09的相互转换,高德,世界测量,百度坐标系的相互转换,坐标系转换
- AJAX跨域请求的理解,JAVA
- Leanote使用mysql_搭建个人Leanote云笔记
- mysql 如何选择2行_MYSQL – 从大表中的第二行中选择数据
- Kafka与ActiveMQ的区别与联系详解
- 前端工作、学习中常用工具推荐
- java监听mysql某张表的insert操作_MySql轻松入门系列————第一站 从源码角度轻松认识mysql整体框架图