一、并发容器

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面试题-并发容器和框架

    1. 如何让一段程序并发的执行,并最终汇总结果? 答:使用CyclicBarrier 和CountDownLatch都可以,使用CyclicBarrier 在多个关口处将多个线程执行结果汇总,Coun ...

  2. 《深入浅出 Java Concurrency》—并发容器 ConcurrentMap

    (转自:http://blog.csdn.net/fg2006/article/details/6404226) 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器 ...

  3. 深入浅出 Java Concurrency (16): 并发容器 part 1 ConcurrentMap (1)[转]

    从这一节开始正式进入并发容器的部分,来看看JDK 6带来了哪些并发容器. 在JDK 1.4以下只有Vector和Hashtable是线程安全的集合(也称并发容器,Collections.synchro ...

  4. 深入浅出 Java Concurrency (27): 并发容器 part 12 线程安全的List/Set[转]

    本小节是<并发容器>的最后一部分,这一个小节描述的是针对List/Set接口的一个线程版本. 在<并发队列与Queue简介>中介绍了并发容器的一个概括,主要描述的是Queue的 ...

  5. 深入浅出 Java Concurrency (21): 并发容器 part 6 可阻塞的BlockingQueue (1)[转]

    在<并发容器 part 4 并发队列与Queue简介>节中的类图中可以看到,对于Queue来说,BlockingQueue是主要的线程安全版本.这是一个可阻塞的版本,也就是允许添加/删除元 ...

  6. 【Java面试】- 并发容器篇

    JDK 提供的并发容器 ConcurrentHashMap: 线程安全的 HashMap CopyOnWriteArrayList: 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vec ...

  7. 深入浅出 Java Concurrency (17): 并发容器 part 2 ConcurrentMap (2)[转]

    本来想比较全面和深入的谈谈ConcurrentHashMap的,发现网上有很多对HashMap和ConcurrentHashMap分析的文章,因此本小节尽可能的分析其中的细节,少一点理论的东西,多谈谈 ...

  8. 深入浅出 Java Concurrency (25): 并发容器 part 10 双向并发阻塞队列 BlockingDeque[转]

    这个小节介绍Queue的最后一个工具,也是最强大的一个工具.从名称上就可以看到此工具的特点:双向并发阻塞队列.所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条 ...

  9. 深入浅出 Java Concurrency (23): 并发容器 part 8 可阻塞的BlockingQueue (3)[转]

    在Set中有一个排序的集合SortedSet,用来保存按照自然顺序排列的对象.Queue中同样引入了一个支持排序的FIFO模型. 并发队列与Queue简介 中介绍了,PriorityQueue和Pri ...

随机推荐

  1. 洛谷——P1405 苦恼的小明

    P1405 苦恼的小明 题目描述 黄小明和他的合伙人想要创办一所英语培训机构,注册的时候要填一张个人情况的表格,在身高一栏小明犯了愁. 身高要求精确到厘米,但小明实在太高了,无法在纸上填下这么长的数字 ...

  2. 【二分答案】bzoj1639 [Usaco2007 Mar]Monthly Expense 月度开支

    #include<cstdio> using namespace std; #define N 100001 int n,m,a[N]; bool check(int x) { int n ...

  3. Exercise03_03

    import java.util.Scanner; public class LinearEquation { public static void main(String[] args){ doub ...

  4. STL之vector3

    描述 将n个数字输入到vector里,并对其进行从大到小排序并输出. 部分代码已经给出,请补充完整,提交时请勿包含已经给出的代码. int main() { vector<int> vec ...

  5. 【PHP手册】 PHP debug_backtrace() 函数

    定义和用法 PHP debug_backtrace() 函数生成一个 backtrace(回溯信息). 该函数返回一个关联数组.下面是可能返回的元素: 名称 类型 描述 function 字符串 当前 ...

  6. SQLSERVER WINDBG调试:mssqlwiki.com

    https://mssqlwiki.com/2012/10/16/sql-server-exception_access_violation-and-sql-server-assertion/ SQL ...

  7. 直接拿来用!最火的iOS开源项目(二)

    每一次的改变总意味着新的开始.”这句话用在iOS上可谓是再合适不过的了.GitHub上的iOS开源项目数不胜数,iOS每一次的改变,总会引发iOS开源项目的演变,从iOS 1.x到如今的iOS 7,有 ...

  8. jQuery用noConflict代替$

    js框架很多的情况下,很容易出现冲突,建议使用noConflict代替$ //消除$对jquery缩写 $.noConflict(); //使用了noConflict后,用$就会无效,应用jQuery ...

  9. openstack学习笔记(一)-openstack的基础知识

    一.OpenStack的基础知识 openstack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache2.0许可证(兼容GPLv3以及DFSG)授权的自由软件和 ...

  10. javascript快速入门6--Script标签与访问HTML页面

    Script标签 script标签用于在HTML页面中嵌入一些可执的脚本 <script> //some script goes here </script> script标签 ...