JavaでのVectorとSynchronizedListの違い

JavaでのVectorとSynchronizedListの違い

こんにちは、私は山を見ています。

この記事はまだJavaのキューについて投げかけています。前回Vector、ArrayList、CopyOnWriteArrayList、SynchronizedListを比較したとき、当時はかなり明確に感じましたが、考えてみたところ理解できなかったので、今日はそれを見つけました。もう一度勉強しました。行き詰まったことは認めます。

Vectorいろいろな問題がありますが、それらはすべて設計上の問題です。次のバージョンで最適化してみませんか?HashMap何度か最適化されています。そして、SynchronizedListこの内部クラス(つまりCollections.synchronizedList(new ArrayList())作成された)もVector同様の同期メソッドを使用します(違いはメソッド本体とメソッドブロックにあり、違いは大きくありません)、なぜそれを放棄Vectorするのですか?

実際、JDKでは外の世界にはさまざまな問題ありますが、というVectorマークは付けられていませんが、JDKの関係者からは、この息子が役に立たないとは考えていませんでした。DeprecatedVector

したがって、使用しないVector理由は2つだけです

  1. 他のキューは、Vector最良のキューよりも適しています
  2. Vectorもが使いにくいと言っているので、もう必要ありません[個人的にはこの確率が高いと感じています]

これはVector主に配列構造であるため、以下の比較のほとんどはArrayList同期パッケージングに関するものです。

VectorそこになぜSynchronizedList

この質問への答えはStackOverflowにあります。

JDK 1.2より前Collectionsは、JDK / JREの一部ではなく、独立したクラスライブラリでした。当時synchronizedは特にパフォーマンスが悪く、多くのシナリオで同期を使用する必要がなかったため、独立クラスライブラリの開発者が同期操作を削除しました。これはArrayList前任者であるはずです。ただし、同期を使用する必要のあるシナリオはまだ少数であるため、SynchronizedListすべてのListサブクラスをラップできるラッパークラスがあります。このクラスはsynchronizedほぼすべてのメソッドに同期を追加します。この設計はVector類似しています。

古代人は「リテラティは軽い」と言っていましたが、実際、コーディングの世界には軽蔑の連鎖があります。私のデザインはあなたのデザインと似ていますが、私のデザインはあなたのデザインよりも優れています。ただし、Collectionsデザインは確かに優れています。

SynchronizedListすべてのList同期に1つ

SynchronizedListポジショニングはパッケージングカテゴリであり、すべてのListサブカテゴリをパッケージ化できますつまり、同期されているArrayListLinkedList同期できるかに関係なく、基盤となるデータ構造はまったく変更されません。これにより、同期が実現されるだけでなく、基盤となるインターフェイスの利点も保持されます。たとえばLinkedList、挿入と削除の効率、ArrayListおよび順次読み取り。さらに、ラッパークラスListすべてのサブクラスの同期要件を解決できるため、実装を繰り返す必要はまったくありません。

比較的言えば、Vectorそれはより圧倒的です。同期したいキューはすべてVector配列構造に変換する必要があります配列ストレージには連続スペースが必要であり、順次読み取り効率は優れていますが、挿入と削除の効率は比較的低いことは誰もが知っています。

イテレータの同期権をユーザーに引き渡します

同期方法SynchronizedListVectorは非常に似ていますが、イテレータ方法の考え方は異なります。

、知っているソースコードを参照してくださいSynchronizedListiteratorし、listIteratorそれはイテレータ時間にブロックされ得ることはありませんので、メソッドが同期されていません。

public Iterator<E> iterator() {
    
    
    return list.iterator(); // Must be manually synched by user!
}

public ListIterator<E> listIterator() {
    
    
    return list.listIterator(); // Must be manually synched by user
}

public ListIterator<E> listIterator(int index) {
    
    
    return list.listIterator(index); // Must be manually synched by user
}

繰り返す必要がある場合はsynchronized、キューオブジェクトを直接ラップするだけです。コードは次のとおりです。

final List<String> list = Collections.synchronizedList(new ArrayList());
list.add("A");
list.add("B");
list.add("C");
final Iterator<String> iterator = list.iterator();

synchronized (list) {
    
    
    while (iterator.hasNext()) {
    
    
        final String next = iterator.next();
        System.out.println(next);
    }
}

Vectorイテレータの実装を見てみましょう

/**
    * An optimized version of AbstractList.Itr
    */
private class Itr implements Iterator<E> {
    
    
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
    
    
        // Racy but within spec, since modifications are checked
        // within or after synchronization in next/previous
        return cursor != elementCount;
    }

    public E next() {
    
    
        synchronized (Vector.this) {
    
    
            checkForComodification();
            int i = cursor;
            if (i >= elementCount)
                throw new NoSuchElementException();
            cursor = i + 1;
            return elementData(lastRet = i);
        }
    }

    public void remove() {
    
    
        if (lastRet == -1)
            throw new IllegalStateException();
        synchronized (Vector.this) {
    
    
            checkForComodification();
            Vector.this.remove(lastRet);
            expectedModCount = modCount;
        }
        cursor = lastRet;
        lastRet = -1;
    }

    // 此处省略一些方法
}

Vectorのイテレータはsynchronized (Vector.this)ロックに使用されます。実際、現在のクラスインスタンスをロックすることもできます。これは、自分で実装したロックメソッドと一致しています。もちろん、この観点からVector、開発者の意識なしに同期によって引き起こされるエラーを確実に回避できることもVector利点です。

Vector完全に役に立たないわけではない

けれどもVector、それは他の場所で失われたCollections、容量拡張の面で他のメリットはまだあります。最初にVector拡張方法を見てください

private void grow(int minCapacity) {
    
    
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                        capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

新しい配列の長さを計算するときにcapacityIncrement、0より大きいかどうかを確認し、大きい場合capacityIncrementはサイズを拡張します。つまり、でVector拡張サイズを指定できます。指定しない場合、拡張はデフォルトArrayList2倍になりますが、1.5倍までしか拡張できず、拡張サイズをカスタマイズする方法はありません。

あなたがそれについて考えるならば、これは役に立たない。

記事の最後の要約

  1. Vector内部構造は配列などCollections.synchronizedList(new ArrayList())です。
  2. Vector拡張サイズを指定できます。デフォルトでは、元の配列の長さの2倍にArrayList拡張されます。拡張サイズを指定することはできず、元の配列サイズの1.5倍に直接拡張されます。
  3. SynchronizedListこれは、Listパフォーマンスの遅延なしに、スレッドセーフでないキューからスレッドセーフなキューまで、すべてのサブクラスを同期キューにラップできるパッケージングクラスVectorあり、直接ラップするだけです。配列ベースの同期キューなどです。キューをに変換するVector必要があります。データのコピーが必要です。
  4. SynchronizedListのイテレータVectorは同期されていないため、ユーザーが実装する必要があります。のイテレータは同期されており、開発者は同期について気にする必要はありません。
  5. VectorこれまでのところマークはなくDeprecated、JDKのリリースに伴い、実装も更新されています。JDKは互換性があることを約束していますが、期限切れとしてマークされておらず、その意図は不明です。

推奨読書

  1. Javaのキューを知る:Vector、ArrayList、CopyOnWriteArrayList、SynchronizedList
  2. 複数のスレッドでArrayListを使用する必要がある場合はどうなりますか?
  3. Java Vector(およびStack)クラスが廃止または非推奨と見なされるのはなぜですか?
  4. Javaでは、VectorとCollections.synchronizedListはすべて同期されていますが、違いは何ですか?

こんにちは、私は山を見ています、パブリックアカウント:山小屋、10歳の類人猿、Apache Storm、WxJava、Cynomysオープンソース寄稿者を見ています。コードの世界で泳ぎ、ドラマでの生活を楽しんでください。

個人ホームページ:https://www.howardliu.cn
個人のブログ記事:のベクトルとCollections.synchronizedListの違い(新しいArrayListを())Javaの
CSDNホームページ:http://blog.csdn.net/liuxinghao
CSDNブログ記事:JavaのベクターCollections.synchronizedList(new ArrayList())との違い

公開番号:山小屋を見る

おすすめ

転載: blog.csdn.net/conansix/article/details/114238758