LinkedList
具有方便的peek
、pop
、...方法。
不幸的是,我需要一个线程安全的LinkedList
。所以,我的第一个想法是将其包装如下:
List<Object> list = Collections.synchronizedList(new LinkedList<>());
但是,由于 List
接口(interface)不包含 peek
或 pop
方法。这当然行不通。
或者,我可以在整个代码中使用 synchronized(list)
block 。这是要走的路吗?
我忽略了任何解决方案吗?
编辑:
使用 LinkedList
的原因有很多。我看到有些人正在提议其他 Collection 。因此,这里遵循简短的要求,这导致我决定使用 LinkedList
。
更多背景信息:
- 我正在使用 LinkedList,因为需要对项目进行排序。
- 应以非阻塞方式添加项目。
- 项目在后面添加;从前面移除。
- 在删除第一项之前,首先需要对其进行
查看
和验证。如果验证失败,则该项目需要保留在列表中。 - 只有当验证成功完成时,才会删除第一个项目。
- 队列需要有一个最大大小(以避免内存问题)。
最佳答案
如果需要peek
要工作,制作一个同步包装器可能还不够,所以你必须写 synchronized
明确地。
与其说是编写包装器的问题,不如说是 peek
的语义问题。方法。不同于 pop
方法,表示单个操作,peek
方法常用于由peek
组成的多组件 Action 中-然后根据什么做其他事情peek
返回。
如果您在包装器中同步,结果将与您手动编写此代码相同:
String s;
synchronized(list) {
s = list.peek();
}
// <<== Problem ==>>
if (s != null) {
synchronized(list) {
s = list.pop();
}
}
这会带来一个问题,因为有时您的列表可能会在 peek
之间发生变化。和 pop
(上面代码中的这个地方被标记为“问题”)。
进行检查和修改的正确方法是在单个 synchronized
中进行 block ,即
synchronized(list) {
String s = list.peek();
if (s != null) {
s = list.pop();
}
}
但是,这不能在简单的包装器中完成,因为两个列表操作在单个 synchronized
中执行 block 。
你可以避免写synchronized
通过构建您自己的封装 LinkedList<T>
的数据结构在多个地方,并提供在同步块(synchronized block)中执行所有测试和修改操作的操作。然而,这不是一个简单的问题,因此您最好以一种可以与预定义的并发容器之一一起工作的方式更改您的算法。
关于java - 同步链表 - peek,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33831871/