Copy-On-Write容器之二:CopyOnWriteArraySet

一、CopyOnWriteArraySet简介

1. CopyOnWriteArraySet继承于AbstractSet,这就意味着它是一个集合。
2. CopyOnWriteArraySet包含CopyOnWriteArrayList对象,它是通过CopyOnWriteArrayList实现的。而CopyOnWriteArrayList本质是个动态数组队列,
所以CopyOnWriteArraySet相当于通过通过动态数组实现的“集合”! CopyOnWriteArrayList中允许有重复的元素;但是,CopyOnWriteArraySet是一个集合,所以它不能有重复集合。因此,CopyOnWriteArrayList额外提供了addIfAbsent()和addAllAbsent()这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作!
至于CopyOnWriteArraySet的“线程安全”机制,和CopyOnWriteArrayList一样,是通过volatile和互斥锁来实现的。这个在前一章节介绍CopyOnWriteArrayList时数据结构时,已经进行了说明,这里就不再重复叙述了。

二、CopyOnWriteArraySet源码分析


2.1、类图结构

2.2、数据结构

2.3、CopyOnWriteArraySet中的lock

并发控制使用CopyOnWriteArrayList的ReentrantLock


2.4、成员变量

private final CopyOnWriteArrayList al;

2.5、构造函数

    public CopyOnWriteArraySet()
    {
        al = new CopyOnWriteArrayList();
    }

2.6、增加元素

    public boolean add(Object obj)
    {
        return al.addIfAbsent(obj);
    }

2.7、remove

    public boolean remove(Object obj)
    {
        return al.remove(obj);
    }

2.8、是否存在元素

    public boolean contains(Object obj)
    {
        return al.contains(obj);
    }

2.9、size

    public int size()
    {
        return al.size();
    }

2.10、clear

    public void clear()
    {
        al.clear();
    }

三、JDK或开源框架中使用

四、示例

package com.dxz.concurrent.cow;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class CopyOnWriteArraySetTest1 {

    // TODO: set是HashSet对象时,程序会出错。
    // private static Set<String> set = new HashSet<String>();
    private static Set<String> set = new CopyOnWriteArraySet<String>();

    public static void main(String[] args) {

        // 同时启动两个线程对set进行操作!
        new MyThread("ta").start();
        new MyThread("tb").start();
    }

    private static void printAll() {
        String value = null;
        Iterator iter = set.iterator();
        while (iter.hasNext()) {
            value = (String) iter.next();
            System.out.print(value + ", ");
        }
        System.out.println();
    }

    private static class MyThread extends Thread {
        MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            int i = 0;
            while (i++ < 10) {
                // “线程名” + "-" + "序号"
                String val = Thread.currentThread().getName() + "-" + (i % 6);
                set.add(val);
                // 通过“Iterator”遍历set。
                printAll();
            }
        }
    }
}

结果:

ta-1, tb-1, 
ta-1, tb-1, 
ta-1, tb-1, ta-1, tb-1, ta-2, 
ta-1, tb-1, ta-2, ta-2, tb-2, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-2, ta-3, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, ta-5, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-3, tb-4, tb-5, tb-0, 
tb-4, tb-5, tb-0, ta-4, ta-5, ta-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, ta-5, ta-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, ta-5, ta-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, ta-5, ta-0, 
ta-1, tb-1, ta-2, tb-2, ta-3, tb-3, tb-4, tb-5, tb-0, ta-4, ta-5, ta-0, 

 

posted on 2012-10-10 15:53  duanxz  阅读(731)  评论(0编辑  收藏  举报