0

Javaでスレッドと同期がどのように機能するかを説明してもらえますか?

高性能なアプリケーションを書きたいです。このアプリケーション内で、ファイルからいくつかのネストされたクラスにデータを読み取ります。これらは基本的にHashMapの基本です。

データの読み取りが終了した後、データを調べてさまざまなチェックを実行する必要があるスレッドを開始します。ただし、スレッドがデータを変更することはありません。

スレッドがデータを変更しないことを保証できる(または少なくとも保証しようとする)場合、データを含むオブジェクトの非同期メソッドを呼び出すためにそれらを使用できますか?

複数のスレッドが、クラスフィールドを変更しないが、いくつかの内部変数を持つ非同期メソッドにアクセスする場合、それは安全ですか?

人工的な例:

public class Data{
// this hash map is filled before I start threads
protected Map<Integer, Spike> allSpikes = new HashMap<Integer, Spike>();

public HashMap returnBigSpikes(){
     Map<Integer, Spike> bigSpikes = new HashMap<Integer, Spike>();

     for (Integer i: allSpikes.keySet()){
         if (allSpikes.get(i).spikeSize > 100){
         bigSpikes.put(i,allSpikes.get(i));
         }
     }

     return bigSpikes;
}
}

スレッドから非同期メソッドreturnBigSpikes()を呼び出しても安全ですか?

このようなユースケースは、制御が難しく、データ(たとえば、返されたbigSpikes)が変更されないため、潜在的に非常に危険であることがわかりました。しかし、私はすでにこのように実装してテストしており、アプリケーションの結果を今すぐ使用して、後でアーキテクチャを変更できるかどうかを知りたいです...

メソッドを同期させるとどうなりますか?アプリケーションのCPUパフォーマンスが1に低下しますか?もしそうなら、どうすればそれを正しく設計し、パフォーマンスを維持できますか?

(メインメモリに約20〜40 Gbのデータ(ログメッセージ)を読み込んでからスレッドを実行します。スレッドはすべてのデータを調べて相関関係を見つける必要があります。各スレッドは分析するメッセージの一部にすぎません。分析のために、スレッドはその部分からの各メッセージをデータからの他の多くのメッセージと比較する必要があります。そのため、スレッドが同期せずにデータを読み取ることを最初に許可することにしました)。

事前にどうもありがとうございました。

4

6 に答える 6

3

すべてのスレッドが開始する前にが入力されている場合は、変更できないマップallSpikesとして保存することで、後で変更されないようにすることができます。

不変であると仮定するSpikeと、メソッドは完全に安全に同時に使用できます。

于 2013-03-21T14:52:35.777 に答える
1

実質的に不変のもの(たとえば、finalキーワードを使用)があり、unmodizableMapを使用している限り、すべて問題ありません。

次のUnmodizableDataをお勧めします。

public class UnmodifiableData {
     final Map<Integer,Spike>  bigSpikes;
     public UnmodifiableData(Map<Integer,Spike> bigSpikes) {
         this.bigSpikes = Collections.unmodifiableMap(new HashMap<>(bigSpikes));
     }
     ....

}

于 2013-03-22T10:10:26.027 に答える
1

一般に、1つのスレッドのみがリソースを変更し、残りはそのリソースのみを読み取ることを保証できるスレッドが多数ある場合、そのリソースへのアクセスを同期する必要はありません。この例では、メソッドreturnBigSpikes()が呼び出されるたびに、bigSpikesハッシュマップの新しいローカルコピーが作成されるため、ハッシュマップを作成している場合でも、各スレッドに固有であるため、同期の問題は発生しません。

于 2013-03-21T14:59:02.910 に答える
0

あなたの計画はうまくいくはずです。synchronize読み取る必要はなく、書き込むだけです。

ただし、将来、すべてのスレッドが同じマップを取得するようにキャッシュする場合は、bigSpikes同期についてさらに注意する必要があります。

于 2013-03-21T14:51:18.843 に答える
0

ConcurrentHashMapを使用すると、すべての同期作業が自動的に行われます。その賭けは、通常のHashMapを中心にシンロナイズを行います。

于 2013-03-21T14:52:08.107 に答える
0

allSpikesはスレッドを開始する前に初期化されるため、安全です。同時実行性の問題は、スレッドがリソースに書き込み、他のスレッドがリソースから読み取る場合にのみ発生します。

于 2013-03-21T14:52:35.843 に答える