每天一例多线程[day13]-----同步类容器和并发类容器

对Vector、ArrayList在迭代的时候如果同时对其进行修改就会抛出java.util.ConcurrentModificationException

如:

 
  1. package com.jeff.base.coll012;

  2.  
  3. import java.util.Iterator;

  4. import java.util.Vector;

  5.  
  6. /**

  7. * 多线程使用Vector或者HashTable的示例(简单线程同步问题)

  8. * @author jeff

  9. */

  10. public class Tickets {

  11.  
  12. public static void main(String[] args) {

  13. //初始化火车票池并添加火车票:避免线程同步可采用Vector替代ArrayList HashTable替代HashMap

  14.  
  15. final Vector<String> tickets = new Vector<String>();

  16.  
  17. //Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());

  18.  
  19. for(int i = 1; i<= 1000; i++){

  20. tickets.add("火车票"+i);

  21. }

  22.  
  23. for (Iterator iterator = tickets.iterator(); iterator.hasNext();) {

  24. String string = (String) iterator.next();

  25. tickets.remove(20);

  26. }

  27.  
  28. // for(int i = 1; i <=10; i ++){

  29. // new Thread("线程"+i){

  30. // public void run(){

  31. // while(true){

  32. // if(tickets.isEmpty()) break;

  33. // System.out.println(Thread.currentThread().getName() + "---" + tickets.remove(0));

  34. // }

  35. // }

  36. // }.start();

  37. // }

  38. }

  39. }

 

打印:

[javascript] view plain copy

  1. <code class="language-java">Exception in thread "main" java.util.ConcurrentModificationException  
  2.     at java.util.Vector$Itr.checkForComodification(Vector.java:1156)  
  3.     at java.util.Vector$Itr.next(Vector.java:1133)  
  4.     at com.jeff.base.coll012.Tickets.main(Tickets.java:24)</code>  

但是Vector集合是线程安全,当我们修改为以下时:

 
  1. package com.jeff.base.coll012;

  2.  
  3. import java.util.Iterator;

  4. import java.util.Vector;

  5.  
  6. /**

  7. * 多线程使用Vector或者HashTable的示例(简单线程同步问题)

  8. * @author jeff

  9. */

  10. public class Tickets {

  11.  
  12. public static void main(String[] args) {

  13. //初始化火车票池并添加火车票:避免线程同步可采用Vector替代ArrayList HashTable替代HashMap

  14.  
  15. final Vector<String> tickets = new Vector<String>();

  16.  
  17. //Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());

  18.  
  19. for(int i = 1; i<= 1000; i++){

  20. tickets.add("火车票"+i);

  21. }

  22.  
  23. // for (Iterator iterator = tickets.iterator(); iterator.hasNext();) {

  24. // String string = (String) iterator.next();

  25. // tickets.remove(20);

  26. // }

  27.  
  28. for(int i = 1; i <=10; i ++){

  29. new Thread("线程"+i){

  30. public void run(){

  31. while(true){

  32. if(tickets.isEmpty()) break;

  33. System.out.println(Thread.currentThread().getName() + "---" + tickets.remove(0));

  34. }

  35. }

  36. }.start();

  37. }

  38. }

  39. }

则多个线程可以正常从集合中删除元素而毫无影响!

 

同步类容器

  同步类容器都是线程安全的,如古老的Vector、Hashtable。这些容器的同步功能其实都是有jdk的Colletions.synchronized等

 工厂方法去创建实现的。其底层的机制无非就是用传统的synchronized关键字对每个公用的方法都进行同步,使得每次只能

 有一个线程访问容器的状态。可以看出性能时很低的。

 

并发类容器

  jdk5.0以后提供了多种并发类容器来替代同步类容器从而改善性能。
 同步类容器的状态都是串行化的。他们虽然线程安全,但是严重降低了并发性,在多线程环境时,
 严重降低应系统的吞吐量。
 并发类容器时专门为并发设计的,使用concurrentHashMap来替代给予散列的传统Hasttable,而且
 在ConcurrentHastMap中,添加了一些常见的复合操作的支持。以及使用了CopyOnWriteArrayList来代替
 Vector,并发的CopyOnWriteSet,一级并发的Queue,ConcurrrentLinkedQueue和LinkedBlockingQUeue,

 前者时高性能的队列,后者时阻塞队列,具体实现Queue还有很多,例如:

 ArrayBlockQueue、PriorituBlockingQueue、SynchronousQueue

 

ConcurrentHashMap

ConcurrentMap接口有两个重要实现:
 * ConcurrentHashMap
 * ConcurrentSkipListMap(支持并发排序功能,弥补ConcurrentHashMap)
 * ConcurrentHashMap内部使用段Segment来表示这些不同的部分,每个段其实就是一个小的hashTable,
 * 他们有自己的锁,只要在多个修改操作发生在不同的段上,他们就可以并发进行,把一个整体分成了16个段segment,

 * 也就是最高支持16个线程的并发修改操作。这也是多线程场景时减小锁粒度从而降低锁竞争的一种方案。

比如t1和t2两个线程访问同一个Segment进行写操作,那么只能等一个线程释放锁后另外一个线程才能继续操作。而t3线程写操作访问的是其他segement则无影响。

 
  1. package com.jeff.base.coll013;

  2.  
  3. import java.util.Iterator;

  4. import java.util.Map;

  5. import java.util.concurrent.ConcurrentHashMap;

  6. import java.util.concurrent.CopyOnWriteArrayList;

  7. import java.util.concurrent.locks.ReentrantReadWriteLock;

  8.  
  9. /**

  10. * 并发类容器:

  11. * jdk5.0以后提供了多种并发类容器来替代同步类容器从而改善性能。

  12. * 同步类容器的状态都是串行化的。他们虽然线程安全,但是严重降低了并发性,在多线程环境时,

  13. * 严重降低应系统的吞吐量。

  14. * 并发类容器时专门为并发设计的,使用concurrentHashMap来替代给予散列的传统Hasttable,而且挨饿

  15. * 在ConcurrentHastMap中,添加了一些常见的复合操作的支持。以及使用了CopyOnWriteArrayList来代替

  16. * Vector,并发的CopyOnWriteSet,一级并发的Queue,ConcurrrentLinkedQueue和LinkedBlockingQUeue,

  17. * 前者时高性能的队列,后者时阻塞队列,具体实现Queue还有很多,例如:

  18. * ArrayBlockQueue、PriorituBlockingQueue、SynchronousQueue

  19. *

  20. * ConcurrentMap接口有两个重要实现:

  21. * ConcurrentHashMap

  22. * ConcurrentSkipListMap(支持并发排序功能,弥补ConcurrentHashMap)

  23. * ConcurrentHashMap内部使用段Segment来表示这些不同的部分,每个段其实就是一个小的hashTable,

  24. * 他们有自己的锁,只要在多个修改操作发生在不同的段上,他们就可以并发进行,把一个整体分成了16个段segment,

  25. * 也就是最高支持16个线程的并发修改操作。这也是多线程场景时减小锁粒度从而降低锁竞争的一种方案。

  26. *

  27. *

  28. * @author jeffSheng

  29. *

  30. */

  31. public class UseConcurrentMap {

  32.  
  33. public static void main(String[] args) {

  34. ConcurrentHashMap<String, Object> chm = new ConcurrentHashMap<String, Object>();

  35. chm.put("k1", "v1");

  36. chm.put("k2", "v2");

  37. chm.put("k3", "v3");

  38. //如果存在k4则不再添加

  39. chm.putIfAbsent("k4", "vvvv");

  40. //System.out.println(chm.get("k2"));

  41. //System.out.println(chm.size());

  42.  
  43. for(Map.Entry<String, Object> me : chm.entrySet()){

  44. System.out.println("key:" + me.getKey() + ",value:" + me.getValue());

  45. }

  46.  
  47.  
  48.  
  49. }

  50. }

 

CopyOnWrite

 
  1. package com.jeff.base.coll013;

  2.  
  3. import java.util.concurrent.CopyOnWriteArrayList;

  4. import java.util.concurrent.CopyOnWriteArraySet;

  5.  
  6. /**

  7. * Copy-On-Write简称COW,是一种用于程序设计中的优化策略。

  8. * JDK里的COW容器有两种个:CopyOnWriteArrayList和CopyOnWriteArraySet

  9. * COW容器非常有用,可以在很多并发场景中使用到。

  10. * 什么时CopyOnWrite容器?

  11. * CopyOnWrite容器即写时复制容器。通俗理解就是当我们往一个容器添加元素的时候,不直接往当前容器添加,

  12. * 而是先将当前容器进行Copy,复制出一个新的容器,然后向新容器中添加元素,添加完元素后,再将原来容器的引用

  13. * 指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发读。,而不需要加锁,因为当前容器不会添加任何

  14. * 元素。所以CoptOnWrite容器也是一种读写分离的思想,读和写不同的容器。

  15. * @author jeffSheng

  16. *

  17. */

  18. public class UseCopyOnWrite {

  19.  
  20. public static void main(String[] args) {

  21.  
  22. CopyOnWriteArrayList<String> cwal = new CopyOnWriteArrayList<String>();

  23. CopyOnWriteArraySet<String> cwas = new CopyOnWriteArraySet<String>();

  24.  
  25.  
  26. }

  27. }

copyOnWriteArrayList的add方法底层是加锁,所以对于CopyOnWrite容器适合用于读多写少的场景,写操作太多,第一要复制原来容器的数据,这个过程比较耗时,第二是存在锁的竞争消耗CPU。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值