LinkedList
有方便的peek
,pop
,...方法。
不幸的是,我需要线程安全LinkedList
。所以,我的第一个想法是将其包装如下:
List<Object> list = Collections.synchronizedList(new LinkedList<>());
但是,由于List
界面不包含peek
或pop
方法。当然,这不起作用。
或者,我可以在整个代码中使用synchronized(list)
块。这是要走的路吗?
我忽视的任何解决方案?
修改
使用LinkedList
的原因有很多。我看到有些人提出了其他收藏品。因此,请遵循简要要求,这导致我决定使用LinkedList
。
更多背景资料:
peek
编辑和验证。如果验证失败,则该项目需要保留在列表中。答案 0 :(得分:4)
如果您需要peek
工作,那么制作同步包装可能还不够,因此您必须明确地编写synchronized
。
编写包装器并不是一个问题,因为它是peek
方法的语义问题。与表示单个操作的pop
方法不同,peek
方法通常用于由peek
组成的多组件操作,然后根据{{1}执行其他操作返回。
如果在包装器中进行同步,结果将与手动编写此代码的结果相同:
peek
这会出现问题,因为您的列表可能会在String s;
synchronized(list) {
s = list.peek();
}
// <<== Problem ==>>
if (s != null) {
synchronized(list) {
s = list.pop();
}
}
和peek
之间发生变化(以上代码中的此位置标记为&#34;问题&#34 ;)
进行检查和修改的正确方法是在单个pop
块中进行,即
synchronized
但是,这不能在一个简单的包装器中完成,因为在一个synchronized(list) {
String s = list.peek();
if (s != null) {
s = list.pop();
}
}
块中执行了两个列表操作。
您可以通过构建自己的封装synchronized
的数据结构来避免在多个位置编写synchronized
,并提供在同步块中执行所有测试和修改操作的操作。但是,这不是一个简单的问题,因此您最好以一种可以使用预定义并发容器之一的方式更改算法。
答案 1 :(得分:2)
您想要的是并发Queue
。 LinkedList
实施List
,Deque
和Queue
。 Queue
是使用peek和pop赋予它FIFO(在后面添加,从前面删除)语义的原因。
LinkedBlockingQueue可以限制,这是您的标准之一。还有其他几个并发队列和Deques可供选择。