太原软件测试培训
达内太原软件测试培训中心

0351-5618167

热门课程

太原软件测试培训--java中 CopyOnWriteArrayList 的使用

  • 时间:2016-07-26 10:09
  • 发布:ImportNew
  • 来源:ImportNew

太原软件测试培训--java中 CopyOnWriteArrayList 的使用

java中,List在遍历的时候,如果被修改了会抛出java.util.ConcurrentModificationException错误。

看如下代码:

import java.util.ArrayList;

import java.util.List;

public class Resource3 {

public static void main(String[] args) throws InterruptedException {

List a = new ArrayList();

a.add("a");

a.add("b");

a.add("c");

final ArrayList list = new ArrayList(

a);

Thread t = new Thread(new Runnable() {

int count = -1;

@Override

public void run() {

while (true) {

list.add(count++ + "");

}

}

});

t.setDaemon(true);

t.start();

Thread.currentThread().sleep(3);

for (String s : list) {

System.out.println(s);

}

}

}

这段代码运行的时候就会抛出java.util.ConcurrentModificationException错误。这是因为主线程在遍历list的时候,子线程在向list中添加元素。

那么有没有办法在遍历一个list的时候,还向list中添加元素呢?办法是有的。就是java concurrent包中的CopyOnWriteArrayList

先解释下CopyOnWriteArrayList类。

CopyOnWriteArrayList类最大的特点就是,在对其实例进行修改操作(add/remove)会新建一个数据并修改,修改完毕之后,再将原来的引用指向新的数组。这样,修改过程没有修改原来的数组。也就没有了ConcurrentModificationException错误。

看下面的代码:

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.CopyOnWriteArrayList;

public class Resource3 {

public static void main(String[] args) throws InterruptedException {

List a = new ArrayList();

a.add("a");

a.add("b");

a.add("c");

final CopyOnWriteArrayList list = new CopyOnWriteArrayList(a);

Thread t = new Thread(new Runnable() {

int count = -1;

@Override

public void run() {

while (true) {

list.add(count++ + "");

}

}

});

t.setDaemon(true);

t.start();

Thread.currentThread().sleep(3);

for (String s : list) {

System.out.println(list.hashCode());

System.out.println(s);

}

}

}

这段代码在for循环中遍历list的时候,同时会输出listhashcode来看看list是不是同一个list了。

部分输出结果如下:

669661746

a

2119153548

b

471684173

c

550648901

-1

-76447331

0

1638154873

1

921225916

2

1618672031

3

1404182932

4

950140076

5

-610377050

6

-610377050

7

-610377050

8

-610377050

9

-610377050

10

-610377050

11

-610377050

12

从上面的结果很容易就看出来,hashcode变化了多次,说明了list已经不是原来的list对象了。这说明了CopyOnWriteArrayList类的add函数在执行的时候确实是修改了list的数组对象。

add函数的代码:

/**

* Appends the specified element to the end of this list.

*

* @param e element to be appended to this list

* @return true (as specified by {@link Collection#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函数中拷贝了原来的数组并在最后加上了新元素。然后调用setArray函数将引用链接到新数组:

/**

* Sets the array.

*/

final void setArray(Object[] a) {

array = a;

}

好了,今天就给大家讲这么多吧,喜欢我的内容可以关注或者分享(微信公众平台:tytedu)选择太原达内培训,不再孤军奋战,轻轻松松做IT高薪白领。太原达内培训带领有明确目标的学子迈向成功之路!

上一篇:太原软件测试培训--专访John Curran:我们谈谈IPv6连接的安全性
下一篇:太原软件测试培训--有容云:浅谈Docker安全合规建设

利用动态库注入调试SDK

使用 iCloud API 的正确姿势

架构师俱乐部:SDN与云网络安全

AyoActivityNoManifest —— Activity 代理框架

选择城市和中心
贵州省

广西省

海南省