如何高性能操作list

09-12-07 xysniper
    

现在有一个list,多个线程并发访问,有的线程add,有的线程get,请问有什么方法保证这个list数据同步及高性能

我试过了,使用synchronized和ReentrantLock性能都不是很高

    

1
banq
2009-12-07 17:06

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

xysniper
2009-12-07 18:26

我的设计如下:

提取数据线程: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.PersistenceQueue#isEmpty()
	 */
	public boolean isEmpty() {
		return insertList.isEmpty() && updateList.isEmpty();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see util.PersistenceQueue#isStop()
	 */
	public boolean isStop() {
		return isStop;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see util.PersistenceQueue#setStop()
	 */
	public void stopQueue() {
		this.isStop = true;
	}

	/* (non-Javadoc)
	 * @see util.PersistenceQueue#getInsertListSize()
	 */
	public int getInsertListSize() {
		// TODO Auto-generated method stub
		return insertList.size();
	}

	/* (non-Javadoc)
	 * @see util.PersistenceQueue#getUpdateListSize()
	 */
	public int getUpdateListSize() {
		// TODO Auto-generated method stub
		return updateList.size();
	}
}

<p>

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

banq
2009-12-08 09:39

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

参考事件模式

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

xysniper
2009-12-08 10:52

To banq

需要读写锁的,因为一个线程不断地写入这个List,另外一个线程不断地

从List中拿数据,拿走入库后必须将List清空访止同一条数据重复拿走入库,造成数据库中同一条数据重复多次写入,所以才加入同步控制

上面的测试是在我本地,将其放入linux测试机,测式性能还是可以的:

91770条入库/分钟,说明多线程只有在硬件足够强,cpu多的情况下才发挥作用,否则反而更慢

你说的LinkedBlockingQueue我会看一下

[该贴被xysniper于2009-12-08 10:55修改过]

2Go 1 2 下一页