当前位置: 首页 > article >正文

集合线程安全控制-Collections工具类synchronizedXxx()方法

Vector 和 Hashtable都是古老的类,都是线程安全类。尽量少用Hashtable,Vector.

需要创建线程安全的List实现类,也无需使用Vector 实现类

需要创建线程安全的Map实现类,也无需使用Hashtable实现类。

可以使用Collections工具类把HashMap变成线程安全的。

Collections类提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

Java中常用的集合框架的实现类HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和TreeMap都是线程不安全的。如果有多个线程试图修改它们,Collections提供了多个类方法可以把它们包装成线程同步的集合。

Collection c = Collections.synchronizedCollection(new ArrayList());
List list = Collections.synchronizedList(new ArrayList());
Set s = Collections.synchroniezedSet(new HashSet());
Map m = Collections.synchronizedMap(new HashMap());

Collections类的synchronizedXxx()方法 是怎么样确保实现线程安全的呢?

 
class ListHelper <E> {  public List<E> list = Collections.synchronizedList(new ArrayList<E>());  public boolean putIfAbsent(E x) {  synchronized (list) {  boolean absent = !list.contains(x);  if (absent)  list.add(x);  return absent;  }  } 
}  
public static <T> List<T> synchronizedList(List<T> list) {  return (list instanceof RandomAccess ?  new SynchronizedRandomAccessList<T>(list) :  new SynchronizedList<T>(list));  }  
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable 
ArrayList源码实现了RandomAccess,所以创建的应该是SynchronizedRandomAccessList类;
static class SynchronizedRandomAccessList<E>  extends SynchronizedList<E>  implements RandomAccess {  SynchronizedRandomAccessList(List<E> list) {  super(list);  }  SynchronizedRandomAccessList(List<E> list, Object mutex) {  super(list, mutex);  }  public List<E> subList(int fromIndex, int toIndex) {  synchronized(mutex) {  return new SynchronizedRandomAccessList<E>(  list.subList(fromIndex, toIndex), mutex);  }  }  static final long serialVersionUID = 1530674583602358482L;  private Object writeReplace() {  return new SynchronizedList<E>(list);  }  }  
 因为SynchronizedRandomAccessList这个类继承自SynchronizedList,而大部分方法都在SynchronizedList中实现了,所以源码中只包含了很少的方法,但是通过subList方法,我们可以看到这里使用的锁对象为mutex对象,而mutex是在SynchronizedCollection类中定义的,所以再看看SynchronizedCollection这个类中关于mutex的定义部分源码:
static class SynchronizedCollection<E> implements Collection<E>, Serializable {  private static final long serialVersionUID = 3053995032091335093L;  final Collection<E> c;  // Backing Collection  final Object mutex;     // Object on which to synchronize  SynchronizedCollection(Collection<E> c) {  if (c==null)  throw new NullPointerException();  this.c = c;  mutex = this;  }  SynchronizedCollection(Collection<E> c, Object mutex) {  this.c = c;  this.mutex = mutex;  }  
}  
  可以看到mutex就是当前的SynchronizedCollection对象,而SynchronizedRandomAccessList继承自SynchronizedList,SynchronizedList又继承自SynchronizedCollection,所以SynchronizedRandomAccessList中的mutex也就是SynchronizedRandomAccessList的this对象。所以在ListHelper类中使用的锁list对象和SynchronizedRandomAccessList内部的锁是一致的,所以它可以实现线程安全性。   -------》这部分参考博客https://www.cnblogs.com/yaowen/p/5983136.html

public static Map m = Collections.synchronizedMap(new HashMap());

Collections.synchronizedMap()会生成一个名为SynchronizedMap的Map,,它使用委托,将自己所有的Map相关的功能交给传入的

HashMap实现,而自己则主要负责保证线程安全。

首先SynchronizedMap内包装了一个Map;

private static class SynchronizedMap<K,V> implements Map<K,V>,Serializable{private static final long serialVersionUID = 1978198479659L;private final Map<K,V> m;       //Backing Mapfinal Object mutex;             //Object on which to synchronize}

通过mutex实现对这个m的互斥操作。比如,对于Map.get()方法实现如下;

public V get(Object key){

 synchronized (mutex) {return m.get(key);}

}

这个包装的Map可以满足线程安全的要求,但是,它在多线程环境中的性能表现并不太算好。无论是对Map的读取或写入,都需要获取mutex的锁,这会导致所有对Map的操作全部进入等待状态,直到mutex锁可用。如果并发级别不高,一般也够用。

但是在高并发环境中,就不适合,可以使用ConcurrentHashMap。

http://www.lryc.cn/news/2418921.html

相关文章:

  • 飞客蠕虫(Conficker)
  • Python爬虫实战:爬取拉勾网并对其进行数据分析
  • 八段数码管动态显示(汇编+C语言)
  • FastDB 很难得的一篇分析
  • 使用StretchBlt之前一定要用SetStretchBltMode(COLORONCOLOR)
  • 2款安卓漫画阅读器横评:漫画阅读软件哪个好用
  • 世界各国与中国时差查询
  • Sailfish OS
  • 离散数据编码方式总结(OneHotEncoder、LabelEncoder、OrdinalEncoder、get_dummies、DictVectorizer、to_categorical的区别?)
  • java.lang.Integer
  • linux进程优先级与nice,Linux之renice和nice调整进程的优先级
  • ActivityThread源码分析
  • 【工作笔记0010】asp.net后台Request.QueryString获取的url中文参数乱码解决方案
  • UART简介
  • C语言:从零基础到精通—轻松写出第一个C语言程序
  • Xtreme.Toolkit.Pro
  • _Linux结束进程到底有多少种方法?
  • windows密码抓取的多种方法
  • OSIP协议栈(及eXoSIP,Ortp等)使用入门(2)
  • 电路方案分析(七)电源入口欠压保护(阈值设定电路)
  • API::CreateProcess()创建进程失败 返回1
  • 企业网站建设需要多少钱?定制开发费用报价在3000-4000元
  • 什么是线程和应用?线程和进程区别是什么?
  • 软件性能测试怎么做?有哪些常见的技术指标?
  • Python接口测试实战- 接口测试理论
  • Android组织首选项PreferenceScreen及首选项框架 ListPreference
  • http://www.51voa.com/VOA_Special_English/
  • 使用VMware安装Ubuntu虚拟机和VMware Tools
  • 09 内核开发-避免冲突和死锁-spinlock
  • ioctl函数详细说明