我需要一个集合来存储来自许多客户端的大量请求,同时我使用一个线程处理每五秒钟存储的所有请求。那么我应该在java中选择哪个集合以获得最佳效率?很明显,该集合应该是线程安全的,并且每五秒轮询所有元素的效率,对吗?
答案 0 :(得分:4)
在这种情况下,您可以尝试使用ArrayBlockingQueue。
由数组支持的有界阻塞队列。这个队列命令 元素FIFO(先进先出)。队列的负责人就是这样 已经在队列中时间最长的元素。尾巴的 queue是队列中最短时间的元素。 在队列的尾部和队列中插入新元素 检索操作获取队列头部的元素。
这是一个经典的“有界缓冲区”,其中包含固定大小的数组 生产者插入并由消费者提取的元素。一旦 创建后,容量无法改变。试图放置一个元素 进入一个完整的队列将导致操作阻塞;尝试去 从空队列中取一个元素同样会阻塞。
这里有一个 take 方法,它会在不消耗CPU周期的情况下阻塞,直到项目被添加到队列中。它是线程安全的。
答案 1 :(得分:1)
我为这种情况写了一个无锁DoubleBufferedList
。从本质上讲,您可以从多个线程写入它,并且写入将累积。当读取出现时,返回整个列表,同时以线程安全的方式,为写入者创建一个新列表。
此BlockingQueue
与任何Queue
之间的重要区别在于,public class DoubleBufferedList<T> {
// Atomic reference so I can atomically swap it through.
// Mark = true means I am adding to it so momentarily unavailable for iteration.
private AtomicMarkableReference<List<T>> list = new AtomicMarkableReference<>(newList(), false);
// Factory method to create a new list - may be best to abstract this.
protected List<T> newList() {
return new ArrayList<>();
}
// Get and replace with empty the current list - can return null - does not mean failed.
public List<T> get() {
// Atomically grab and replace the list with an empty one.
List<T> empty = newList();
List<T> it;
// Replace an unmarked list with an empty one.
if (!list.compareAndSet(it = list.getReference(), empty, false, false)) {
// Failed to replace!
// It is probably marked as being appended to but may have been replaced by another thread.
// Return empty and come back again soon.
return Collections.<T>emptyList();
}
// Successfull replaced an unmarked list with an empty list!
return it;
}
// Grab and lock the list in preparation for append.
private List<T> grab() {
List<T> it;
// We cannot fail so spin on get and mark.
while (!list.compareAndSet(it = list.getReference(), it, false, true)) {
// Spin on mark - waiting for another grabber to release (which it must).
}
return it;
}
// Release the list.
private void release(List<T> it) {
// Unmark it - should this be a compareAndSet(it, it, true, false)?
if (!list.attemptMark(it, false)) {
// Should never fail because once marked it will not be replaced.
throw new IllegalMonitorStateException("It changed while we were adding to it!");
}
}
// Add an entry to the list.
public void add(T entry) {
List<T> it = grab();
try {
// Successfully marked! Add my new entry.
it.add(entry);
} finally {
// Always release after a grab.
release(it);
}
}
// Add many entries to the list.
public void add(List<T> entries) {
List<T> it = grab();
try {
// Successfully marked! Add my new entries.
it.addAll(entries);
} finally {
// Always release after a grab.
release(it);
}
}
// Add a number of entries.
@SafeVarargs
public final void add(T... entries) {
// Make a list of them.
add(Arrays.<T>asList(entries));
}
}
您需要一次一个地轮询每个条目。这个结构一次性为您提供整个累积列表,包含自您上次查看以来累积的所有内容。
{{1}}
答案 2 :(得分:0)
以我的建议为基础,将时间戳作为键,请求对象作为值的静态ConcurrentHashmap。