欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

就必须做成 图纸加密 强一致性的

点击: 次  来源:宝鼎软件 时间:2017-07-30

原文出处: 五月的仓颉

初识CopyOnWriteArrayList

第一次见到CopyOnWriteArrayList,是在研究JDBC的时候,软件开发,每一个数据库的Driver都是维护在一个CopyOnWriteArrayList中的,为了证明这一点,贴两段代码,第一段在com.mysql.jdbc.Driver下,也就是我们写Class.forName(“…”)中的内容:

public class Driver extends NonRegisteringDriver
  implements java.sql.Driver
{
  public Driver()
    throws SQLException
  {
  }

  static
  {
    try
    {
      DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

看到com.mysql.jdbc.Driver挪用了DriverManager的registerDriver要领,这个类在java.sql.DriverManager下:

public class DriverManager
{
    private static final CopyOnWriteArrayList<DriverInfo> 
    registeredDrivers = new CopyOnWriteArrayList();
    private static volatile int loginTimeout = 0;
    private static volatile PrintWriter logWriter = null;
    private static volatile PrintStream logStream = null;
    private static final Object logSync = new Object();
    static final SQLPermission SET_LOG_PERMISSION = new 
    SQLPermission("setLog");
    ...
}

看到所有的DriverInfo都在CopyOnWriteArrayList中。既然看到了CopyOnWriteArrayList,我自然免不了要研究一番为什么JDK利用的是这个List。

首先提两点:

1、CopyOnWriteArrayList位于java.util.concurrent包下,可想而知,这个类是为并发而设计的

2、CopyOnWriteArrayList,顾名思义,Write的时候老是要Copy,也就是说对付CopyOnWriteArrayList,任何可变的操纵(add、set、remove等等)都是陪伴复制这个行动的,后头会解读CopyOnWriteArrayList的底层实现机制

四个存眷点在CopyOnWriteArrayList上的谜底

就必需做成 图纸加密 强一致性的

如何向CopyOnWriteArrayList中添加元素

对付CopyOnWriteArrayList来说,增加、删除、修改、插入的道理都是一样的,所以用增加元素来阐明一下CopyOnWriteArrayList的底层实现机制就可以了。先看一段代码:

public static void main(String[] args)
{
     List<Integer> list = new CopyOnWriteArrayList<Integer>();
     list.add(1);
     list.add(2);
}

看一下这段代码做了什么,先是第3行的实例化一个新的CopyOnWriteArrayList:

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8673264195747942595L;

    /** The lock protecting all mutators */
    transient final ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray. */
    private volatile transient Object[] array;
    ...
}
public CopyOnWriteArrayList() {
    setArray(new Object[0]);
}
final void setArray(Object[] a) {
    array = a;
}

看到,对付CopyOnWriteArrayList来说,底层就是一个Object[] array,然后实例化一个CopyOnWriteArrayList,用图来暗示很是简朴:

就必需做成 图纸加密 强一致性的

就是这样,Object array指向一个数组巨细为0的数组。接着看一下,第4行的add一个整数1做了什么,add的源代码是:

public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
    Object[] elements = getArray();
    int len = elements.length;
    Object[] newElements = Arrays.copyOf(elements, len + 1);
    newElements[len] = e;
    setArray(newElements);
    return true;
} finally {
    lock.unlock();
}
}

画一张图暗示一下:

就必需做成 图纸加密 强一致性的

每一步都清楚地暗示在图上了,一次add大抵经验了几个步调:

1、加锁

2、拿到原数组,获得新数组的巨细(原数组巨细+1),实例化出一个新的数组来

3、把原数组的元素复制到新数组中去

4、新数组最后一个位置配置为待添加的元素(因为新数组的巨细是凭据原数组巨细+1来的)

5、把Object array引用指向新数组

6、解锁

整个进程看起来较量像ArrayList的扩容。有了这个基本,我们再来看一下第5行的add了一个整数2做了什么,这应该很是简朴了,照旧画一张图来暗示:

就必需做成 图纸加密 强一致性的

和前面差不多,就不表明白。