如果Deque
的大小将超过限制,我需要用新值替换第一个值。我编写了以下代码来解决这个问题:
final class Some {
final int buffer;
final Deque<Operation> operations = new ConcurrentLinkedDeque<>();
// constructors ommited;
@Override
public void register(final Operation operation) {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
}
@Override
public void apply() {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
}
}
如您所见,我有两种修改 Deque
的方法。我怀疑在多线程环境下,此代码是否能正常运作。问题是:检查 size()
,然后再执行修改 ConcurrentLinkedDeque
操作,是否安全?我想尽量减少锁的使用。如果此代码无法工作,则必须引入锁机制,那么使用 ConcurrentLinkedDeque()
就没有意义了。
final class Some {
final int buffer;
final Deque<Operation> operations = new LinkedList<>();
final Lock lock = new ReentrantLock();
// constructors ommited;
@Override
public void register(final Operation operation) {
this.lock.lock();
try {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
} finally {
lock.unlock();
}
}
@Override
public void apply() {
this.lock.lock();
try {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
} finally {
this.lock.unlock();
}
}
}
这是使用 Lock
的替代方案。这是实现我想要的唯一方法吗?我特别想尝试使用并发集合。
ConcurrentLinkedDeque#size()
需要完全扫描,并且可能会因并发添加/删除而变化。您最好使用ArrayDeque
和您的锁定代码。 - Ben Manes