2

我的应用程序需要保留对某个资源的请求访问日志,并且多个线程将记录日志条目。唯一相关的信息是请求的时间戳,正在检索的统计数据将是在最后 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;
    }
}

我的问题是:

  1. 这种使用会ReentrantLock确保线程安全吗?
  2. 是否需要使用锁定getTrailingStats
  3. 我可以使用synchronized积木来完成所有这些吗?我使用锁的原因是因为我希望在 R 和 W 部分拥有相同的锁,以便列表中第一个元素(最近添加的条目)的写入和读取一次完成一个线程,我无法做到这一点synchronized
  4. 我应该改用ReentrantReadWriteLock吗?
4

1 回答 1

3

锁可能会成为主要的性能瓶颈。另一种方法是使用ConcurrentLinkedDeque:用于offerFirst添加新元素,并使用(弱一致)iterator(不会抛出 a ConcurrentModificationException)代替您的 for-each 循环。优点是这将比您的实现或实现好得多synchronizedList,但缺点是迭代器是弱一致的 - thread1 可能会在 thread2 迭代它时将元素添加到列表中,这意味着 thread2 不会计数那些新元素。但是,这在功能上等同于让 thread2 锁定列表,以便 thread1 无法添加到它 - 无论哪种方式 thread2 都不计算新元素。

于 2013-07-25T02:39:43.933 回答