こんにちは、私は山を見ています。
この記事はまだJavaのキューについて投げかけています。前回Vector、ArrayList、CopyOnWriteArrayList、SynchronizedListを比較したとき、当時はかなり明確に感じましたが、考えてみたところ理解できなかったので、今日はそれを見つけました。もう一度勉強しました。行き詰まったことは認めます。
Vector
いろいろな問題がありますが、それらはすべて設計上の問題です。次のバージョンで最適化してみませんか?HashMap
何度か最適化されています。そして、SynchronizedList
この内部クラス(つまりCollections.synchronizedList(new ArrayList())
作成された)もVector
同様の同期メソッドを使用します(違いはメソッド本体とメソッドブロックにあり、違いは大きくありません)、なぜそれを放棄Vector
するのですか?
実際、JDKでは、外の世界にはさまざまな問題がありますが、というVector
マークは付けられていませんが、JDKの関係者からは、この息子が役に立たないとは考えていませんでした。Deprecated
Vector
したがって、使用しないVector
理由は2つだけです。
- 他のキューは、
Vector
最良のキューよりも適しています - 誰
Vector
もが使いにくいと言っているので、もう必要ありません[個人的にはこの確率が高いと感じています]
これは
Vector
主に配列構造であるため、以下の比較のほとんどはArrayList
同期パッケージングに関するものです。
Vector
そこになぜSynchronizedList
この質問への答えはStackOverflowにあります。
JDK 1.2より前Collections
は、JDK / JREの一部ではなく、独立したクラスライブラリでした。当時synchronized
は特にパフォーマンスが悪く、多くのシナリオで同期を使用する必要がなかったため、独立クラスライブラリの開発者が同期操作を削除しました。これはArrayList
前任者であるはずです。ただし、同期を使用する必要のあるシナリオはまだ少数であるため、SynchronizedList
すべてのList
サブクラスをラップできるラッパークラスがあります。このクラスはsynchronized
、ほぼすべてのメソッドに同期を追加します。この設計はVector
類似しています。
古代人は「リテラティは軽い」と言っていましたが、実際、コーディングの世界には軽蔑の連鎖があります。私のデザインはあなたのデザインと似ていますが、私のデザインはあなたのデザインよりも優れています。ただし、Collections
デザインは確かに優れています。
SynchronizedList
すべてのList
同期に1つ
SynchronizedList
ポジショニングはパッケージングカテゴリであり、すべてのList
サブカテゴリをパッケージ化できます。つまり、同期されているArrayList
かLinkedList
同期できるかに関係なく、基盤となるデータ構造はまったく変更されません。これにより、同期が実現されるだけでなく、基盤となるインターフェイスの利点も保持されます。たとえばLinkedList
、挿入と削除の効率、ArrayList
および順次読み取り。さらに、ラッパークラスList
はすべてのサブクラスの同期要件を解決できるため、実装を繰り返す必要はまったくありません。
比較的言えば、Vector
それはより圧倒的です。同期したいキューはすべてVector
配列構造に変換する必要があります。配列ストレージには連続スペースが必要であり、順次読み取り効率は優れていますが、挿入と削除の効率は比較的低いことは誰もが知っています。
イテレータの同期権をユーザーに引き渡します
同期方法SynchronizedList
とVector
は非常に似ていますが、イテレータ方法の考え方は異なります。
、知っているソースコードを参照してくださいSynchronizedList
にiterator
し、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
拡張サイズを指定できます。指定しない場合、拡張はデフォルトArrayList
で2倍になりますが、1.5倍までしか拡張できず、拡張サイズをカスタマイズする方法はありません。
あなたがそれについて考えるならば、これは役に立たない。
記事の最後の要約
Vector
内部構造は配列などCollections.synchronizedList(new ArrayList())
です。Vector
拡張サイズを指定できます。デフォルトでは、元の配列の長さの2倍にArrayList
拡張されます。拡張サイズを指定することはできず、元の配列サイズの1.5倍に直接拡張されます。SynchronizedList
これは、List
パフォーマンスの遅延なしに、スレッドセーフでないキューからスレッドセーフなキューまで、すべてのサブクラスを同期キューにラップできるパッケージングクラスでVector
あり、直接ラップするだけです。配列ベースの同期キューなどです。キューをに変換するVector
必要があります。データのコピーが必要です。SynchronizedList
のイテレータVector
は同期されていないため、ユーザーが実装する必要があります。のイテレータは同期されており、開発者は同期について気にする必要はありません。Vector
これまでのところマークはなくDeprecated
、JDKのリリースに伴い、実装も更新されています。JDKは互換性があることを約束していますが、期限切れとしてマークされておらず、その意図は不明です。
推奨読書
- Javaのキューを知る:Vector、ArrayList、CopyOnWriteArrayList、SynchronizedList
- 複数のスレッドでArrayListを使用する必要がある場合はどうなりますか?
- Java Vector(およびStack)クラスが廃止または非推奨と見なされるのはなぜですか?
- 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())との違い