从Linkedlist中删除节点的线程安全方法。
public void delete(String x, LinkedList<String> list)
{
String lock = "false";
for (int i = 0; i < list.size(); i++) {
synchronized (lock) {
if (list.get(i).equals(x)) {
lock = "true";
list.remove(i);
}
lock = "false";
}
}
}
非常感谢!
编辑:上面的方法是线程安全的,但其性能需要提高。这是一个面试问题。
答案 0 :(得分:3)
在方法本地的对象上进行同步并没有真正做任何有用的事情。此外,覆盖对同步块内锁定的对象的引用是有目的的混淆。关于该代码的目的的一些解释可能有助于我们帮助您改进它:)
实际问题。 get(i)
和remove(i)
都要求您将列表迭代到位置i。如果使用列表的实际迭代器和迭代器的remove方法,则只需迭代整个列表一次。
答案 1 :(得分:2)
主题安全的:
public void delete(String x, LinkedList<String> list) {
synchronized (list) {
for (Iterator<String> it = list.iterator(); it.hasNext();)
if (it.next().equals(x)) it.remove();
}
}
但是,很可能,你的问题不是线程安全。您在遍历列表时使用了list.delete()
并获得了ConcurrentModificationException
。如果是这种情况,请随意删除同步块。
答案 2 :(得分:1)
我会使用List.removeAll
List<String> list = new LinkedList<>();
list.addAll(Arrays.asList("a,b,c,d,a,b,c,d,e,a,b,a,b".split(",")));
System.out.println("Before removeAll(a) " + list);
list.removeAll(Collections.singleton("a"));
System.out.println("After removeAll " +list);
打印
Before removeAll(a) [a, b, c, d, a, b, c, d, e, a, b, a, b]
After removeAll [b, c, d, b, c, d, e, b, b]
答案 3 :(得分:0)
尝试为同步集合使用现成的Java Collections API功能。 Official documentation.
您还可以使用迭代器删除项目。正如文件所述:
如果使用显式迭代器,则必须调用迭代器方法 来自同步块内。不遵循这个建议可能会 导致不确定的行为。
答案 4 :(得分:0)
public void delete (String x, LinkedList<String> list) {
synchronized (list) {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String y = it.next();
if (x.equals(y)) {
it.remove();
}
}
}
}
答案 5 :(得分:0)
public void delete(String x, LinkedList<String> list){
Set<String> target = Collections.singleton(x);
synchronized (list) {
list.removeAll( target );
}
}
两件事:
"false"
是一个实习字符串,所有在"false"
上同步的代码片段都会被同步,但这是一种hackish方式获得应用程序范围的同步,可能根本不是你想要的。您应该在列表上进行同步。使用列表的每个人都应该在列表上进行同步。虽然最好的做法是首先使用同步集合,但不需要在使用代码中使用明确的synchronized
块。removeAll
通常是从集合中删除所有出现的一个或多个对象的最有效方法。在最坏的情况下,它相当于迭代集合并使用迭代器来移除项(这是LinkedList
的情况),但对于某些实现(如ArrayList
),它被设为效率更高。答案 6 :(得分:0)