2009-02-22 9 views
11

私は、これは本当に愚かな質問ですが、ここに行く恐れる:クリア()のimpl

はなぜJavaのデフォルトのLinkedListの実装の明確な方法は、リストを歩くと、すべてのノードを外すためにわざわざでしょうか?なぜヘッダーを外してリストの残りの部分を接続したままにしておかないのですか?GCはとにかくそれを取得しますか?

は、ここでの方法です:

/** 
* Removes all of the elements from this list. 
*/ 
public void clear() { 
    Entry<E> e = header.next; 
    while (e != header) { 
     Entry<E> next = e.next; 
     e.next = e.previous = null; 
     e.element = null; 
     e = next; 
    } 
    header.next = header.previous = header; 
    size = 0; 
modCount++; 
} 

なぜそれを歩きますか?なぜheader.next = header.previous = header;にスキップしてみませんか?

最高の私はそれがGCを助けるのですか?このリンクhttp://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html#997442のことを示唆している。

TIA ...

答えて

18

彼らの方法は、他のコードはまだ特定のノードへの参照を保持している場合でも、他のノードがGC'edされることを保証します。

ノードの1つに外部参照が1つでもあっても、チェーン全体が収集されないことがあります。

また、一覧内の他の操作が同時に行われている可能性があります(例:subList()またはCollections.unmodifiableList()のイテレータを介したビュー)。これにより、リストがすぐに「空」と認識されます。

+0

私は、外部コードがLinkedList $ Entryへの参照を取得する方法がないと言っていますが、間接的にLinkedList $ ListItrを使用すると、確かに可能です。 – overthink

+0

ノードを保持するのは何ですか? IteratorまたはsubListですが、これらは有効ではないので、残っていることはありません。 –

+0

@Tom:これをしなかった場合、subListとIteratorは引き続き動作しますが、コレクションフレームワークはフェイルファーストを試みますが、保証はできません。 –

2

IIRCこれは、特定の(世代別の)GCアルゴリズムのパフォーマンスを助けるためにJDK6で行われた変更です。多くの場合、List自身と古いノードは、他のノードの一部より古い世代になります。若い世代はより頻繁に収集され、その結果、若いノードはすべてのノードがゴミであることが発見される前にコピーされます。

これはマイナーなパフォーマンスの最適化です。メモリパフォーマンスの最適化は、しばしば、実行に時間がかかる問題を引き起こすコードではないという点で少し奇妙です。

0

私のゲーム開発ブログでは、この問題をちょうど推測していました。答えをありがとう。私は、ノードの露出が疑わしい設計上の余裕であったと主張します。また、リスト(反復子など)の代替ビューがノードのリンク解除に依存してフェイル・ファーストになることも概要です。この副作用の振る舞いに頼る代わりに、リストのサブビューは変更数をチェックする必要があります。いずれにせよ、なぜ彼らは今それにこだわっているのか分かります。

0

ソースコードjava.util.LinkedListhttp://developer.classpath.org/doc/java/util/LinkedList-source.html)は、最初と最後の要素をnullに設定することができます。

もちろん保護過剰になりがちな場合は、すべてをループすることができます。私はあなたのリストが何千もの要素を保持するならば、これは非常に高価な仕事かもしれないと個人的に考える。

関連する問題