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面试题-并发容器和框架
1. 如何让一段程序并发的执行,并最终汇总结果? 答:使用CyclicBarrier 和CountDownLatch都可以,使用CyclicBarrier 在多个关口处将多个线程执行结果汇总,Coun ...
- 《深入浅出 Java Concurrency》—并发容器 ConcurrentMap
(转自:http://blog.csdn.net/fg2006/article/details/6404226) 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器 ...
- 深入浅出 Java Concurrency (16): 并发容器 part 1 ConcurrentMap (1)[转]
从这一节开始正式进入并发容器的部分,来看看JDK 6带来了哪些并发容器. 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器,Collections.synchro ...
- 深入浅出 Java Concurrency (27): 并发容器 part 12 线程安全的List/Set[转]
本小节是<并发容器>的最后一部分,这一个小节描述的是针对List/Set接口的一个线程版本. 在<并发队列与Queue简介>中介绍了并发容器的一个概括,主要描述的是Queue的 ...
- 深入浅出 Java Concurrency (21): 并发容器 part 6 可阻塞的BlockingQueue (1)[转]
在<并发容器 part 4 并发队列与Queue简介>节中的类图中可以看到,对于Queue来说,BlockingQueue是主要的线程安全版本.这是一个可阻塞的版本,也就是允许添加/删除元 ...
- 【Java面试】- 并发容器篇
JDK 提供的并发容器 ConcurrentHashMap: 线程安全的 HashMap CopyOnWriteArrayList: 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vec ...
- 深入浅出 Java Concurrency (17): 并发容器 part 2 ConcurrentMap (2)[转]
本来想比较全面和深入的谈谈ConcurrentHashMap的,发现网上有很多对HashMap和ConcurrentHashMap分析的文章,因此本小节尽可能的分析其中的细节,少一点理论的东西,多谈谈 ...
- 深入浅出 Java Concurrency (25): 并发容器 part 10 双向并发阻塞队列 BlockingDeque[转]
这个小节介绍Queue的最后一个工具,也是最强大的一个工具.从名称上就可以看到此工具的特点:双向并发阻塞队列.所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条 ...
- 深入浅出 Java Concurrency (23): 并发容器 part 8 可阻塞的BlockingQueue (3)[转]
在Set中有一个排序的集合SortedSet,用来保存按照自然顺序排列的对象.Queue中同样引入了一个支持排序的FIFO模型. 并发队列与Queue简介 中介绍了,PriorityQueue和Pri ...
随机推荐
- 10、Flask实战第10天:视图使用装饰器
在实际开发中,我们有时候会用到自己定义装饰器并应用到函数视图或者类视图里面:比如:我们要想进入个人中心页面,首先要验证你是否登录,否则进不去,下面我们来模拟这个场景 定义一个装饰器 from func ...
- POJ 1486 Sorting Slides(二分图匹配)
[题目链接] http://poj.org/problem?id=1486 [题目大意] 给出每张幻灯片的上下左右坐标,每张幻灯片的页码一定标在这张幻灯片上, 现在问你有没有办法唯一鉴别出一些幻灯片 ...
- Vimperator常用快捷键
分别往下/往上滚动窗口一行 j/k 左右滚动窗口 h/l 向下/向上滚动一屏的窗口 <Space>/<C-b> 向下/向上滚动半屏的窗口 <C-d>/< ...
- 十. 图形界面(GUI)设计10.菜单
有两种类型的菜单:下拉式菜单和弹出式菜单.本章只讨论下拉式菜单编程方法.菜单与JComboBox和JCheckBox不同,它们在界面中是一直可见的.菜单与JComboBox的相同之处是每次只可选择一个 ...
- HTML-DEV-ToolLink(常用的在线字符串编解码、代码压缩、美化、JSON格式化、正则表达式、时间转换工具、二维码生成与解码等工具,支持在线搜索和Chrome插件。)
HTML-DEV-ToolLink:https://github.com/easonjim/HTML-DEV-ToolLink 常用的在线字符串编解码.代码压缩.美化.JSON格式化.正则表达式.时间 ...
- 在WPF中合并两个ObservableCollection
WPF中的ObservableCollection是一个非常常用的集合对象,我们可以通过将它绑定到ListBox之类的集合控件上时,当集合发生变更时,会同步更新到界面上.但是,有的时候我们需要合并两个 ...
- springmvc-框架学习
https://www.androiddev.net/springmvc-框架学习一-helloworld/
- [SpringMVC+redis]自定义aop注解实现控制器访问次数限制
原文:http://www.cnblogs.com/xiaoyangjia/p/3762150.html?utm_source=tuicool 我们需要根据IP去限制用户单位时间的访问次数,防止刷手机 ...
- python的dict如何排序
Python的内置dictionary数据类型是无序的,通过key来获取对应的value.可是有时我们需要对dictionary中 的item进行排序输出,可能根据key,也可能根据value来排 # ...
- [Python爬虫] 之二十三:Selenium +phantomjs 利用 pyquery抓取智能电视网数据
一.介绍 本例子用Selenium +phantomjs爬取智能电视网(http://news.znds.com/article/news/)的资讯信息,输入给定关键字抓取资讯信息. 给定关键字:数字 ...