如何高性能操作list

现在有一个list,多个线程并发访问,有的线程add,有的线程get,请问有什么方法保证这个list数据同步及高性能
我试过了,使用synchronized和ReentrantLock性能都不是很高

如果是以读为主,以写为辅助,可以使用读写锁,readwritelock

我的设计如下:
提取数据线程:1
作用:将xml数据压入ConcurrentLinkedQueue队列
分发线程
数量:3
作用:从ConcurrentLinkedQueue取数据,select db后,将其数据根据特点插入两个不同的java.util.ArrayList中
处理线程
数量:1
作用:从上面的ArrayList中取出使用ibatis的batch insert or batch
update插入或更新到数据库中
性能如下:
入库数据:603~644条/分钟
前提:我的ArrayList中使用了ReentrantReadWriteLock控制同步,代码如下:
总结:是不是读写锁性能不可观呢?多线程后还不如单线程快呀


/**
*
*/

package util;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.Logger;

import vo.SubscriberState;

public class DataPersistenceQueue implements PersistenceQueue {
private final ReentrantReadWriteLock rwlfi = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock rwlfu = new ReentrantReadWriteLock();
private final Lock ri = rwlfi.readLock();
private final Lock wi = rwlfi.writeLock();
private final Lock ru = rwlfu.readLock();
private final Lock wu = rwlfu.writeLock();
private Logger log = Logger.getLogger(DataPersistenceQueue.class);
private List insertList = new ArrayList();
private List updateList = new ArrayList();
private boolean isStop = false;

public DataPersistenceQueue() {
isStop = false;
}

public void insertList(SubscriberState substate) {
wi.lock();
try {
insertList.add(substate);
} finally {
wi.unlock();
}
}

/**
* @return the insertQueue
*/

public List<SubscriberState> getInsertList() {
ri.lock();
try {
return new ArrayList(insertList);
} finally {
insertList.clear();
ri.unlock();
}
}


public void updateList(SubscriberState substate) {
wu.lock();
try {
updateList.add(substate);
} finally {
wu.unlock();
}
}

/**
* @return the updateQueue
*/

public List<SubscriberState> getUpdateList() {
ru.lock();
try {
return new ArrayList(updateList);
} finally {
updateList.clear();
ru.unlock();
}
}


/*
* (non-Javadoc)
*
* @see util.PersistenceQueueisEmpty()
*/

public boolean isEmpty() {
return insertList.isEmpty() && updateList.isEmpty();
}

/*
* (non-Javadoc)
*
* @see util.PersistenceQueueisStop()
*/

public boolean isStop() {
return isStop;
}

/*
* (non-Javadoc)
*
* @see util.PersistenceQueuesetStop()
*/

public void stopQueue() {
this.isStop = true;
}

/* (non-Javadoc)
* @see util.PersistenceQueuegetInsertListSize()
*/

public int getInsertListSize() {
// TODO Auto-generated method stub
return insertList.size();
}

/* (non-Javadoc)
* @see util.PersistenceQueuegetUpdateListSize()
*/

public int getUpdateListSize() {
// TODO Auto-generated method stub
return updateList.size();
}
}



[该贴被xysniper于2009-12-07 18:40修改过]

你如果是读取整个List,就不必用读写锁,可以参考LinkedBlockingQueue,使用事件Queue异步就可以了,

参考事件模式
推荐你从模式角度考虑,是这样可以理清思路。

To banq
需要读写锁的,因为一个线程不断地写入这个List,另外一个线程不断地
从List中拿数据,拿走入库后必须将List清空访止同一条数据重复拿走入库,造成数据库中同一条数据重复多次写入,所以才加入同步控制
上面的测试是在我本地,将其放入linux测试机,测式性能还是可以的:
91770条入库/分钟,说明多线程只有在硬件足够强,cpu多的情况下才发挥作用,否则反而更慢
你说的LinkedBlockingQueue我会看一下
[该贴被xysniper于2009-12-08 10:55修改过]

2009年12月08日 10:52 "xysniper"的内容
To banq
需要读写锁的,因为一个线程不断地写入这个List,另外一个线程不断地
从List中拿数据,拿走入库后必须将List清空访止同一条数据重复拿走入库,造成数据库中同一条数据重复多次写入,所以才加入同步控制

你的这个情形是典型异步观察者Queue模式,可以使用LinkedBlockingQueue完成。再往大扩展,可使用JMS。

别忘记使用ThreadPoolExecutor之类,性能要更快些:


ExecutorService executor = new ThreadPoolExecutor(numberOfThreads, numberOfThreads, //
60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());


[该贴被banq于2009-12-08 14:09修改过]

是使用了ThreadPoolExecutor,用的是ArrayBlockingQueue,不知两个性能哪个高?没有测试过

看看CopyOnWriteArrayList

建议你看下,是否在已经建立索引的表上 进行插入,那样会很慢

优化七:一条sql插入多个值。

继续的插入优化,插入经过上次的优化之后,又开始了下一轮的优化。这次着重在如何提高数据库的写入速度。开始我们为了加快插入速度,使用的是iBATIS的批量提交,从理论上讲应该会比一条条的插入快,因该是常识吧。但是这次事实上告诉我,仅仅是把批量提交去掉就已经提高了3倍多,更牛B的在后面。

陶方建议一个sql插入多个值,形如insert into tableName (x,xx,xxx) values(x,xx,xxx),(xx,xxx,xxxx)…,经过这样修改之后,在我看来,速度已经很疯狂了.