2009-10-19 3 views
8

この質問は、Javaコレクション(特にHashtableとVector)に関連していますが、他の場所にも適用される可能性があります。インターフェイスへのプログラミングと同期されたコレクション

私は多くの場所でプログラムのインターフェースがどれくらい良いのかを読んだことがあります。私は100%同意します。たとえば、基本的な実装を考慮しなくても、Listインタフェースにプログラムする機能は、デカップリングとテストの目的で最も効果的です。コレクションでは、内部ストレージ構造やランダムアクセス時間などの違いを考慮して、ArrayListとLinkedListが異なる状況下でどのように適用されるかを確認できます。ただし、これらの2つの実装は同じインターフェイスで使用できます。素晴らしいです。

私は配置できないようなものは、同期化された実装(特にHashtableとVector)がこれらのインタフェースにどのように適合しているかです。私にとって、彼らはモデルに合うようには見えない。基礎となるデータ構造の実装の大部分は、データの格納方法(LinkedList、Array、ソート済みツリーなど)が異なるように見えますが、同期はデータにアクセスできる条件(ロック条件)を処理します。メソッドがMapコレクションを返す例を見てみましょう。アプリケーションが並行性を全く考慮していないとしましょう。この場合、メソッドはインターフェイスを介して返す実装に関係なく操作します。誰もが満足しています。世界は安定している。

ただし、アプリケーションで並行性の面で注意が必要な場合はどうなりますか?基本的な実装を考慮せずに操作することはできません.Hashtableは問題ありませんが、他の実装も必要です。

1)コレクションを追加/削除するときに同期ブロックなどを使用して同期を強制します。しかし、同期化された実装(Hashtable)が返された場合、これは過度のものにならないでしょうか?

2)メソッドシグネチャを変更してHashtableを返します。しかし、これはHashtableの実装に密接に結びついており、その結果、インターフェイスへのプログラミングの利点がウィンドウの外に投げ捨てられます。

3)コンカレント・パッケージを使用し、メソッド・シグネチャを変更してConcurrentMapインタフェースの実装を戻します。私には、これは前進のようだ。

本質的に、同期化の問題は、インターフェイスにプログラミングする際に、基本的な実装について考えさせるようにするという点で、コレクションフレームワーク内でのミスフィットのようなものです。

ここでポイントが完全に不足していますか?

ありがとうございました。

+2

キーは、ここで、またはそこにいくつかの 'synchronized'キーワードを追加すると、あなたのプログラムをスレッドセーフにしないということです。 'java.util.concurrent'コレクションでも、それらをプライベートな実装の詳細として保持したいとします。 –

答えて

6

1)はい、それはやり過ぎ
2)正しいだろうが、それは
3)は、状況に依存行われるべきではありません。あなたが既に知っているよう

事は、ある、インターフェースにプログラミングが

同期は、その後の実装(rememberから削除されました(それはそれをしないではないか、それは実装があります)アプリケーションが何をするのか説明し、ベクトルとHastable前ですjava 1.2には後でArrayListとHasMapが同期化されていませんでしたが、それぞれListとMapのインタフェースが実装されていました)、過度の同期化のためにパフォーマンスが低下するためです。たとえば、単一のスレッドでベクトルを使用する場合、その単一のスレッド内ではまだ同期が取られています。

複数のスレッド間でデータ構造を共有することは、アプリケーションを設計するときに考慮する必要があります。ここでは、使用する方法を選択し、データ状態をきれいに保つ責任を負う者を選択します。

ここでは、言及したオプション1または3のいずれかを選択します。手動の同期がありますか?同期インターフェースを使用すべきですか?どのバージョンの私たちは、あなたが1を選ぶならば、あなたも自分のデザインに特定の実装(すなわちベクトル)

データ同期が「運」であなたを本当に起こるものではありませんを拒否することができるなどなど。例えば

をサポートしますそれが正しく起こるように設計しなければならず、それが解決するより多くの問題を引き起こさない。

この設計では、使用するオプション(実装)および/または使用するインフラストラクチャに注意する必要があります。

過度の同期化を回避する最も簡単な方法は、不変のデータを使用し、他のスレッドとデータを共有しないことです。

Martin Fowler氏によるコンピューティングを分散する第一法則に非常によく似た何か:

「したがって、我々は分散オブジェクト設計の私の第一法則に取得する:あなたのオブジェクトを配布しないでください。」

マルチスレッド・アプリケーションの第一法則は次のようになります。

マルチスレッド・アプリケーションの第一法則:あなたのデータを共有しませんか?

:)

最後の注意:Collectionsクラスは、いくつかのインターフェイスの "同期" バージョンを提供:

Synchronized List
Synchronized Map
Synchronized Set

0

JavaのVectorHashtableVectorが書かれた時点ではJDK 5で追加されました現在の同時実行パッケージに先行、人々は同期化させるためには良いアイデアだと思いました、そして、彼らはおそらく、企業での使用にパフォーマンス壁にぶつかります。同時実行性は、コード間のモジュール化が必ずしもうまくいかない状況の1つです。

+1

これはもう少し長く描かれています.1.4では、java.util.Collections.synchronizedMapとHashtableの代わりに使用することが推奨されている友人との更新されたコレクションフレームワークが導入されました。そして、1.5は全体の並行パッケージをもたらしました。 しかし、Hashtableはまだ標準ライブラリの周りに散らばっていて、おそらくこれ以上のものになるでしょう... "Javaのアプローチ"は、同期が実装の詳細であると思われ、API宣言。 – araqnid

+0

Seconded。これらのクラスは両方とも歴史的なもので、Java 1.0にまでさかのぼります。彼らは1.2にまで遡ると確信していますが、古代のAPIをオンラインで見ることはできません。 –

+0

@araqnidでは、「Javaアプローチ」の方法は、長年にわたり血液やパフォーマンス、同時性などの傷跡で描かれています。特に、サーバ側での使用が始まって以来、シンプルな「新しいVector()」と比較して、スケールは依存性注入、コード間インタフェース、アーキテクチャ宇宙飛行士の方向に向っています。 –

1

あなたが苦労しているのは、マルチスレッド環境では、クライアントが変更可能な共有状態のオブジェクトを純粋に使用できないという事実です。コレクションインターフェイスは、オブジェクト自体を安全に使用する方法については何も教えてくれません。 ConcurrentMapを返すと、いくつかの追加情報が得られますが、その特定の場合のみです。

通常、ドキュメント(javadocなど)またはJava Concurrency in Practice.に記載されているカスタム注釈を使用して、スレッドセーフティの問題を個別に伝える必要があります。返されるオブジェクトのクライアントは、独自のロックメカニズムを使用する必要があります。提供する。このインタフェースは、通常、スレッドの安全性に対して直交しています。

クライアントがすべての実装がConcurrent実装からのものであることが分かっていても、その情報はインタフェース自体によって通信されない場合は問題ありません。

0

HashtableVectorは非常に古いですが、 JDK 1.0から。彼らはJDK1.2の標準コレクションの前にあり、長い間前から新しいコードで使用すべきではありません。代わりにまたはCollections.synchronizedList()でラップされたHashMapおよびArrayListを使用してください。

何かがJDKに導入されたときのバージョンは、APIドキュメントのSinceタグで確認できます。

関連する問題