机制:
CopyOnWriteArrayList:专为多线程并发设计的容器,“写入时复制”策略。
Collections.synchronizedMap:同步容器,独占策略。
结果:在两个线程下Collections.synchronizedMap访问时间大概是CopyOnWriteArrayList的5倍,但在64线程的时候就变成了200倍+。所以如果在容器完全只读的情况下CopyOnWriteArrayList绝对是首选。但CopyOnWriteArrayList采用“写入时复制”策略,对容器的写操作将导致的容器中基本数组的复制,性能开销较大。所以但在有写操作的情况下,CopyOnWriteArrayList性能不佳,而且如果容器容量较大的话容易造成溢出。代码中如果CopyOnWriteArrayList cl按照ArrayList al的方法初始化就会造成溢出。
代码如下:
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author Alfred Xu <alfred.xu@heweisoft.com>
*
*/
public class ListPerformance {
private final int threadNumber;
public ListPerformance(int n) {
threadNumber = n;
}
private static class TestThread implements Runnable {
private static long totolTime;
private final int No;
private final int loop = 100000;
private final Thread t;
private final List<Integer> list;
TestThread(int No, List<Integer> list) {
this.No = No;
this.list = list;
t = new Thread(this);
}
public void start() {
t.start();
}
public synchronized void addTime(long time) {
totolTime += time;
}
@Override
public void run() {
long time = randomAccess();
addTime(time);
}
@Override
public String toString() {
return "Thread " + No + ":";
}
public long randomAccess() {
Date date1 = new Date();
Random random = new Random();
for (int i = 0; i < loop; i++) {
int n = random.nextInt(loop);
list.get(n);
}
Date date2 = new Date();
long time = date2.getTime() - date1.getTime();
// System.out.println(this + list.getClass().getSimpleName()
// + " time:" + time);
return time;
}
}
public void initList(List<Integer> list, int size) {
for (int i = 0; i < size; i++) {
list.add(new Integer(i));
}
}
public void test(List<Integer> list) {
System.out.println("Test List Performance");
TestThread[] ts = new TestThread[threadNumber];
for (int i = 0; i < ts.length; i++) {
ts[i] = new TestThread(i, list);
}
for (int i = 0; i < ts.length; i++) {
ts[i].start();
}
}
public static void main(String[] args) {
ListPerformance lp = new ListPerformance(64);
List<Integer> al = Collections
.synchronizedList(new ArrayList<Integer>());
lp.initList(al, 100000);
lp.test(al);
System.out.println(al.size());//在此处设置断点 等待创建线程完全 否则看不到效果
System.out.println(TestThread.totolTime);
TestThread.totolTime = 0;
CopyOnWriteArrayList<Integer> cl = new CopyOnWriteArrayList<Integer>(al);
lp.test(cl);
System.out.println(cl.size());//在此处设置断点 等待创建线程完全 否则看不到效果
System.out.println(TestThread.totolTime);
}
}