我的应用程序需要保留对特定资源的请求的访问日志,并且多个线程将记录日志条目。唯一相关的信息是请求的时间戳,检索的统计信息将是最后X秒发生的请求数。返回给定秒数的统计信息的方法也需要支持多个线程。
我正在考虑使用Locks框架来处理并发处理,我不是最熟悉的,因此这个问题。这是我的代码:
import java.util.LinkedList;
import java.util.concurrent.locks.ReentrantLock;
public class ConcurrentRecordStats
{
private LinkedList<Long> recLog;
private final ReentrantLock lock = new ReentrantLock();
public LinkedConcurrentStats()
{
this.recLog = new LinkedList<Long>();
}
//this method will be utilized by multiple clients concurrently
public void addRecord(int wrkrID)
{
long crntTS = System.currentTimeMillis();
this.lock.lock();
this.recLog.addFirst(crntTS);
this.lock.unlock();
}
//this method will be utilized by multiple clients concurrently
public int getTrailingStats(int lastSecs)
{
long endTS = System.currentTimeMillis();
long bgnTS = endTS - (lastSecs * 1000);
int rslt = 0;
//acquire the lock only until we have read
//the first (latest) element in the list
this.lock.lock();
for(long crntRec : this.recLog)
{
//release the lock upon fetching the first element in the list
if(this.lock.isLocked())
{
this.lock.unlock();
}
if(crntRec > bgnTS)
{
rslt++;
}
else
{
break;
}
}
return rslt;
}
}
我的问题是:
ReentrantLock
使用getTrailingStats
确保线程安全吗?synchronized
使用锁定?synchronized
块执行所有操作吗?我使用锁的原因是因为我想在R和W部分都有相同的锁,以便写入和读取列表中的第一个元素(最近添加的条目)一次完成一个线程我不能只用{{1}}。答案 0 :(得分:3)
锁可能是一个主要的性能瓶颈。另一种方法是使用a ConcurrentLinkedDeque:使用offerFirst
添加新元素,并使用(弱一致)iterator
(不会抛出ConcurrentModificationException
)到位你的每个循环。优点是这将比你的实现或synchronizedList
实现更好地执行,但缺点是迭代器是弱一致的 - thread1可能会在列表迭代时将元素添加到列表中,这意味着thread2不会计算这些新元素。但是,这在功能上等同于让thread2锁定列表,以便thread1无法添加它 - 无论是thread2还是不计算新元素。