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 ...
随机推荐
- sqlplus terminators - Semicolumn (;), slash (/) and a blank line
The problem here is the way SQL*Plus interprets the commands passed to it. Remember the "SQL co ...
- [Codeforces 8D] Two Friends
Brief Introduction: 有两人a.b,他们都在A点,a经过B点到C点,而b直接到C点.a走过的距离不超过la,b走过距离不超过lb,询问他们可能经过最长的公共距离. Algorithm ...
- 【AC自动机】【动态规划】hdu2296 Ring
题解:http://www.cnblogs.com/swm8023/archive/2012/08/08/2627535.html 要输出路径,价值最大优先,价值相同的取长度较小者,仍相同取字典序较小 ...
- 开发板无法ping通虚拟机的问题解决一例
先描述一下遇到的问题: 使用的开发板是Tq2440,我将虚拟机和开发板都设在在了同一个网段,并且虚拟机使用的是桥接的方式,我用nfs的方式挂载根文件系统是失败,系统无法起来,后来我进入uboot命令模 ...
- 【JSP EL】el表达式判断是否为null
后台程序放入Model中,从前台el表达式取出来非常方便,但是如果需要处理 当数据为null的时候,怎么办,不为null的时候,怎么办:这个怎么处理呢? <span class="us ...
- iOS 常用的#define合集
1.定义常量 定义常量的时候最好以小写字母k开头,让人见名知意, (1)导航栏高度:我们都知道iPhone竖屏时候导航栏的高度为44,这时候可以定义一个常量来表示该高度, #define kNaivg ...
- SQL CTE 递归分割以逗号分隔的字符串
)) INSERT INTO @t SELECT 'AAA,BBB,CCC' SELECT * FROM @t ;WITH mycte AS ( ,mend,num FROM @t UNION ALL ...
- java 的 CopyOnWriteArrayList类
初识CopyOnWriteArrayList 第一次见到CopyOnWriteArrayList,是在研究JDBC的时候,每一个数据库的Driver都是维护在一个CopyOnWriteArrayLis ...
- [Android Memory] Android性能测试小工具Emmagee
转载:http://blog.csdn.net/anlegor/article/details/22895993 Emmagee是网易杭州QA团队开发的用于测试指定android应用性能的小工具.该工 ...
- 扩展 jQuery EasyUI Datagrid 数据行鼠标悬停/离开事件(onMouseOver/onMouseOut)
客户需求: jQuery EasyUI Datagrid 用户列表鼠标悬停/离开数据行时显示人员头像(onMouseOver/onMouseOut) 如图所示,Datagrid 鼠标悬停/离开数据行时 ...