一、并发容器

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里的并发容器与安全共享策略总结相关推荐

  1. Java集合之并发容器

    一:java中的并发容器总结 JDK提供的这些容器大部分在 java.util.concurrent 包中. ConcurrentHashMap: 线程安全的HashMap CopyOnWriteAr ...

  2. Java多线程之并发容器(五)

    1.hashtable和vector 它们是支持并发操作的并发容器,hashtable只不过是在hashmap的基础上,所有的方法上都加上synchronized关键字,vector在ArrayLis ...

  3. Java 多线程 —— 常用并发容器

    引言 本博客基于常用的并发容器,简单概括其基本特性和简单使用,并不涉及较深层次的原理分析和全面的场景用法. 适合对不了解并发容器的同学,工作中遇到类似的场景,能够对文中提到的并发容器留有简单印象就好. ...

  4. 【Java多线程】并发容器CopyOnWriteArrayList

    一个不安全的List 预期输出结果为10000,但是实际运行结果为9992,是因为线程不安全,应该使用synchronized同步块 不安全代码 package cn.hanquan.test;imp ...

  5. java 并发queue_深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介

    Queue是JDK 5以后引入的新的集合类,它属于Java Collections Framework的成员,在Collection集合中和List/Set是同一级别的接口.通常来讲Queue描述的是 ...

  6. Java里的容器存放的元素必须是1个对象.

    我们经常看到这个句话: Java里存放的容器只能是1个对象. 一. 值类型和对象类型. 实际上, java里的变量可以分为两种类型, 一种是值类型. 一种是对象类型. 1.1 值类型变量 所谓值类型的 ...

  7. 聊聊并发-Java中的Copy-On-Write容器

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

  8. java高并发(十二)并发容器J.U.C

    并发容器是JDK提供的一个包名:java.util.concurrent ArrayList -> CopyOnWriteArrayList CopyOnWriteArrayList是线程安全的 ...

  9. Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))...

    转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用 1.1. ReentrantLoc ...

最新文章

  1. Linux下root密码忘记的解决办法
  2. ICA处理后,如何判断眼电、心电等成分?
  3. Java判断工作日计算,计算随意2个日期内的工作日
  4. 天题系列: Candy
  5. python 合并重叠数据
  6. MySQL创建索引跳过redo_明明我建了索引,为什么sql执行的还是这么慢?
  7. 计算机玩游戏不能全屏,玩游戏屏幕两边有黑条?教你简单几步轻松解决-win7玩游戏不能全屏...
  8. 「ruby/MiniMagick」用MiniMagick处理图片
  9. Unity3D之NGUI基础7:UI动态加载
  10. popwindow下拉筛选 二级联动_工作录入数据需要三级联动下拉菜单,Excel轻松制作!-Excel教程...
  11. version GLIBC_2.28 not found
  12. python入门教程汇总
  13. Oracle 常用SQL语句大全(精)
  14. wifi 小米pro 驱动 黑苹果_【黑果小兵】小米Pro macOS High Sierra 10.13黑苹果安装教程...
  15. jquery点击图片放大功能
  16. 版本控制工具svn和git
  17. python生成词云图、特殊图形_Python模块---Wordcloud生成词云图
  18. MySQL备份的几种常用方法与恢复步骤
  19. java名片_JavaWeb练习-网上名片管理系统
  20. GAMES101 13节 光线追踪 笔记

热门文章

  1. border-box
  2. SicilyBrackets Matching
  3. 浅析LAN交换机的线速释义 From: www.c114.net
  4. wgs-84,gcj-02,bd-09的相互转换,高德,世界测量,百度坐标系的相互转换,坐标系转换
  5. AJAX跨域请求的理解,JAVA
  6. Leanote使用mysql_搭建个人Leanote云笔记
  7. mysql 如何选择2行_MYSQL – 从大表中的第二行中选择数据
  8. Kafka与ActiveMQ的区别与联系详解
  9. 前端工作、学习中常用工具推荐
  10. java监听mysql某张表的insert操作_MySql轻松入门系列————第一站 从源码角度轻松认识mysql整体框架图