我需要创建一个列表来执行以下操作:
我每微秒从外部队列/主题接收一个对象。
对对象执行一些操作后,我需要将这些对象持久化到数据库中。
我正在做的坚持成批100或1000。唯一的问题是,持久化率低于传入消息率。现在我不想把这个放在一个线程中,因为持久化会减慢消息的消耗。
我的想法是继续接受消息对象并将其添加到集合(如链接列表)
并继续从集合的另一端以100或1000批的方式移除,并持久化到数据库中。
什么是正确的收藏使用?如何同步并避免并发的修改异常?
下面是我试图用arraylist实现的代码,它在持久化时每隔几秒钟清除一次列表。
class myclass{
List persistList;
ScheduledExecutorService persistExecutor;
ScheduledFuture scheduledFuture;
PersistOperation persistOperation;
//Initialize delay, interval
void init(){
scheduledFuture=persistExecutor.scheduleAtFixedRate(new persistOperation(persistList), delay, interval, TimeUnit.SECONDS);
}
void execute(msg){
//process the message and add to the persist list
}
class PersistOperation implements Runnable{
List persistList
PersistOperation(List persistList){
//Parameterized constructor
}
run(){
//Copy persistList to new ArrayList and clear persistList
//entity manager persist/update/merge
}
}
}
最佳答案
并继续从集合的另一端以100或1000批的方式移除,并持久化到数据库中。
只要从集合中轮询多个线程,这是合理的。
下面是我试图用arraylist实现的代码ArrayList
在这里是一个错误的选择,因为它不是线程安全的,并且在移除索引0
处的元素时,它右边的每个元素都必须移位(一个O(n)
操作)。
您要查找的集合称为Deque
,否则称为双端队列。但是,因为您需要集合是线程安全的,所以我建议使用ConcurrentLinkedDeque
。