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 メソッドを使用すると、リスト全体を 1 回反復するだけで済みます。

于 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

これを使用-> 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 Collections 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 に答える
0
public void delete(String x, LinkedList<String> list){
    Set<String> target = Collections.singleton(x);
    synchronized (list) {
        list.removeAll( target );
    }
}

2つのこと:

  1. 作成したばかりの文字列を同期しても何も起こりません (厳密にはそうではありません。これ"false"はインターンされた文字列であるため、同期するすべてのコードが同期され"false"ますが、これはアプリケーション全体の同期を取得するためのハックな方法です。あなたが意図した)。リストで同期する必要があります。リストを使用するすべての人が、リスト上で同期している必要があります。synchronized最初に同期コレクションを使用することをお勧めしますが、使用するコードで明示的なブロックを使用する必要はありません。
  2. removeAllコレクションから 1 つまたは複数のオブジェクトをすべて削除するには、通常、これが最も効率的な方法です。最悪の場合、コレクションを繰り返し処理し、イテレータを使用してアイテムを削除することと同じですが ( の場合LinkedList)、一部の実装 ( などArrayList) では、より効率的になるように作られています。
于 2012-05-07T21:51:26.367 に答える