文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JAVA数据结构篇--13线程安全的Set 集合

2023-08-17 07:10

关注

前言:java 中用于存放不重复元素的set 集合,其中无序的HashSet,以及有序的LinkedHashSet和TreeSet 都是非线程安全的,那么多线程环境下,我们要存放不重复的元素,需要使用哪种集合进行数据存取;

1 使用:

 Set set = Collections.synchronizedSet(new LinkedHashSet<>(10, 0.75f)); CopyOnWriteArraySet copyOnWriteArraySet = new CopyOnWriteArraySet<>(); Set setFromMap = Collections.newSetFromMap(new ConcurrentHashMap<>()); User userOne = new User(); userOne.setId(1).setName("lisi").setAge(20); set.add(userOne); copyOnWriteArraySet.add(userOne); setFromMap.add(userOne); User userTwo = new User(); userTwo.setId(2).setName("wangwu").setAge(20); set.add(userTwo); copyOnWriteArraySet.add(userTwo); setFromMap.add(userTwo); set.remove(userTwo); Iterator iterator1 = set.iterator(); while (iterator1.hasNext()) {     User user = (User) iterator1.next();     System.out.println("user = " + user); }

2 过程:
2.1 放入获取元素:
Collections.synchronizedSet:通过使用synchronized 关键字修饰达到线程安全的目的

public Iterator iterator() {     return c.iterator(); // Must be manually synched by user! } public boolean add(E e) {     synchronized (mutex) {return c.add(e);} } public boolean remove(Object o) {     synchronized (mutex) {return c.remove(o);} }

CopyOnWriteArraySet<>():通过CopyOnWriteArrayList实现,也即底层数据结构使用的数组

private final CopyOnWriteArrayList al;  public CopyOnWriteArraySet() {     al = new CopyOnWriteArrayList(); }public boolean add(E e) {// 当元素不存在的时候添加元素    return al.addIfAbsent(e);}publicboolean addIfAbsent(E e) {   Object[] snapshot = getArray();   return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :       addIfAbsent(e, snapshot);}private boolean addIfAbsent(E e, Object[] snapshot) {   final ReentrantLock lock = this.lock;   // 获取锁   lock.lock();   try {       Object[] current = getArray();       int len = current.length;       if (snapshot != current) {// 当前的数组长度不等于传入进来的数组长度           // Optimize for lost race to another addXXX operation           // 从现有数组中判断要存入的e元素是否已经存在,存在直接返回false           int common = Math.min(snapshot.length, len);           for (int i = 0; i < common; i++)               if (current[i] != snapshot[i] && eq(e, current[i]))                   return false;           if (indexOf(e, current, common, len) >= 0)                   return false;       }       // 数组赋值       Object[] newElements = Arrays.copyOf(current, len + 1);       newElements[len] = e;       setArray(newElements);       return true;   } finally {   //  释放锁       lock.unlock();   }}// 移除元素public boolean remove(Object o) {    Object[] snapshot = getArray();    // 元素存在则进行移除否则直接返回    int index = indexOf(o, snapshot, 0, snapshot.length);    return (index < 0) ? false : remove(o, snapshot, index);} private boolean remove(Object o, Object[] snapshot, int index) {    final ReentrantLock lock = this.lock;    lock.lock();// 获取锁    try {        Object[] current = getArray();        int len = current.length;        //  a: { break a; } 语法将a:之后的代码成为一个方法体,遇到 break跳出方法体        if (snapshot != current) findIndex: {// 如果数组长度已经发生变化            int prefix = Math.min(index, len);            for (int i = 0; i < prefix; i++) {                if (current[i] != snapshot[i] && eq(o, current[i])) {                    index = i;                    break findIndex;                }            }            if (index >= len)                return false;            if (current[index] == o)                break findIndex;            index = indexOf(o, current, index, len);            if (index < 0)                return false;        }        // 数组长度-1        Object[] newElements = new Object[len - 1];        // 赋值剩下的元素到新的数组中        System.arraycopy(current, 0, newElements, 0, index);        System.arraycopy(current, index + 1,                         newElements, index,                         len - index - 1);        setArray(newElements);        return true;    } finally {        lock.unlock();    }}// 元素遍历:public Iterator iterator() {    return al.iterator();}// CopyOnWriteArrayList 下iteratorpublic Iterator iterator() {    return new COWIterator(getArray(), 0);}private COWIterator(Object[] elements, int initialCursor) {    cursor = initialCursor;    snapshot = elements;}public boolean hasNext() {    return cursor < snapshot.length;}public boolean hasPrevious() {    return cursor > 0;}@SuppressWarnings("unchecked")public E next() {    if (! hasNext())        throw new NoSuchElementException();    return (E) snapshot[cursor++];}

Collections.newSetFromMap(new ConcurrentHashMap<>()):使用ConcurrentHashMap实现元素的存取:

public static  Set newSetFromMap(Map map) {    return new SetFromMap<>(map);}private final Map m;  // The backing mapprivate transient Set s;       // Its keySetSetFromMap(Map map) {    if (!map.isEmpty())        throw new IllegalArgumentException("Map is non-empty");    m = map;    s = map.keySet();}public boolean remove(Object o)   { return m.remove(o) != null; }public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }public Iterator iterator()     { return s.iterator(); }

3 总结:
3.1 Collections.synchronizedSet() 工具类通过对方法增加synchronized 关键字修饰达到线程安全的目的;CopyOnWriteArraySet 通过ReentrantLock 获取和释放锁达到线程安全的目的;Collections.newSetFromMap(new ConcurrentHashMap<>()) 借用ConcurrentHashMap 线程安全的Map集合达到线程安全的目的;
3.2 Collections.synchronizedSet() 工具类直接使用synchronized,并发情况下性能较差;CopyOnWriteArraySet 借助CopyOnWriteArrayList 使用ReentrantLock 性能好一些,但是底层使用了数组,占用内存较多;Collections.newSetFromMap(new ConcurrentHashMap<>()) 通过ConcurrentHashMap性能较好;

来源地址:https://blog.csdn.net/l123lgx/article/details/128504721

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯