0

从链表中删除节点的线程安全方法。

 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";
            }
        }
   }

非常感谢!

编辑:上述方法是线程安全的,但其性能需要提高。这是一道面试题。

4

7 回答 7

3
  1. 在方法本地的对象上同步并没有真正做任何有用的事情。此外,覆盖对您在同步块内锁定的对象的引用在目的上令人困惑。关于该代码用途的一些解释可能会帮助我们帮助您改进它:)

  2. 实际的问题。 get(i)两者remove(i)都要求您将列表迭代到位置 i。如果使用列表的实际迭代器和迭代器的 remove 方法,则只需迭代整个列表一次。

于 2012-05-07T20:00:30.190 回答
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. 如果是这种情况,请随时删除同步块。

于 2012-05-07T20:01:54.340 回答
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]
于 2012-05-07T20:17:01.493 回答
0
public void delete(String x, LinkedList<String> list){
    Set<String> target = Collections.singleton(x);
    synchronized (list) {
        list.removeAll( target );
    }
}

两件事情:

  1. 在刚刚创建的字符串上同步什么都不做(嗯,不完全是,因为"false"是一个实习字符串,所有同步的代码都"false"将被同步,但这是一种获取应用程序范围同步的黑客方法,可能根本不是什么你打算)。您应该在列表上进行同步。使用列表的每个人都应该在列表上同步。尽管更好的做法是首先使用同步集合,从而消除synchronized使用代码中显式块的需要。
  2. removeAll通常是从集合中删除所有出现的一个或多个对象的最有效方法。在最坏的情况下,它等同于遍历集合并使用迭代器来删除项目(这是 的情况LinkedList),但对于某些实现(如ArrayList),它变得更加高效。
于 2012-05-07T21:51:26.367 回答
0

使用这个-> http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#synchronizedList(java.util.List )

于 2012-05-08T16:39:13.427 回答
0

尝试使用开箱即用的 Java 集合 API 功能来同步集合。官方文档。

您也可以使用迭代器来删除项目。正如文件所述:

如果使用显式迭代器,则必须从同步块中调用迭代器方法。不遵循此建议可能会导致不确定的行为。

于 2012-05-07T20:01:56.647 回答
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();
                    }
                }
            }
        }
于 2012-05-07T20:43:16.553 回答