ホームページ  >  記事  >  Java  >  スレッド セーフに関する Java コレクションのクラス

スレッド セーフに関する Java コレクションのクラス

高洛峰
高洛峰オリジナル
2017-01-23 16:42:501220ブラウズ

Java コレクション内のクラスはスレッド セーフです

スレッド セーフ クラス

コレクション フレームワークでは、一部のクラスはスレッド セーフであり、これらはすべて jdk1.1 に表示されます。 jdk1.2以降、多くの非スレッドセーフクラスが登場しました。 これらのスレッドセーフな同期クラスは次のとおりです:

vector: arraylist よりも 1 つ多くの同期メカニズム (スレッド セーフ) があり、効率が低いため、使用は推奨されません。 Web アプリケーション、特にフロントエンド ページでは、効率 (ページの応答速度) が優先されることがよくあります。

statck: スタッククラス、先入れ後出力

hashtable: ハッシュマップよりもスレッドセーフ

enumeration: 列挙、イテレータと同等

これらに加えて、他のクラスとインターフェースは非スレッドセーフです。

スレッドセーフ クラスのメソッドは同期されており、一度に 1 つだけアクセスできます。重量物なので効率が低いです。

その他:

1. ハッシュテーブルとハッシュマップの違い

ハッシュテーブルはスレッドセーフです。つまり、ハッシュテーブルメソッドは同期メカニズムを提供しません。つまり、同期メカニズムを提供しません。 hashtable では null 値の挿入は許可されません。

2. 複数のスレッドがコレクションを同時に変更する場合はどうなりますか

古い Vector/Hashtable クラスを使用してください

StringBuffer はスレッド セーフですが、StringBuilder はスレッド セーフではありません。安全性と安全性について深く理解していないと、StringBuffer のすべての操作がスレッドセーフであるかのような錯覚を起こしやすくなります。ただし、Java によって保証されるスレッド安全性は、そのメソッドの実行が排他的であることを意味します。オブジェクト自体を複数回呼び出しても、安全です。以下の例を見てください。 StringBufferTest には、展開に使用されるデータ メンバーの内容があります。ただし、複数の追加の組み合わせはスレッド セーフではありません。ただし、キーワード synchronized をログおよび getContest メソッドに追加すると、結果が非​​常に整理されます。StringBuider に変更するか、途中で追加する場合でも、これに基づいて動作する他のスレッドに道を譲ることになります。 StringBuilder と StringBuffer はまったく同じであり、マルチスレッドとシングルスレッドの問題です。スレッドが同じ StringBuffer の append メソッドを呼び出した場合、それがスレッド セーフであるかどうかとは関係がありません。追加された一連の文字列が混乱するという結果にならない限り、それはスレッド セーフではないことを意味します。スレッド セーフとは、常に 1 つのスレッドだけが重要なリソースにアクセスできることを意味します。スレッド セーフとは、一連の操作が同期されていることを意味するのではなく、特定のメソッドを実行するときに他のスレッドが変更できないことを意味します。クラスがスレッドセーフであるかどうかは、複数のスレッドが同時に実行されていることに依存し、これらのスレッドは特定のメソッドを同時に実行する可能性があります。ただし、各操作の結果はシングルスレッド実行の場合と同じであるため、スレッドセーフであると言えます。ログ メソッドはロックされていないため、追加ロックが解放された後、誰もが CPU の実行フラグメントを取得する可能性があります。

ただし、マルチスレッドの安全性を誤解しないでください:

public class StringBufferTest {
  private StringBuffer contents = new StringBuffer();
  public void log(String message){
   contents.append(System.currentTimeMillis());
   contents.append("; ");
   contents.append(Thread.currentThread().getName());
   for(int i=0;i<10000;i++){
    contents.append(i);  
     contents.append(message);  //append本身是线程安全的,修改contents时,其它线程无法访问。
     contents.append("\n");
   }
   contents.append("\n\n");
  }
  public void getContents(){
   System.out.println(contents);
  }
}
 
class RunThread extends Thread{
  String message;
  StringBufferTest buffer;
  public RunThread(StringBufferTest buffer, String message){
   this.buffer = buffer;
   this.message = message;
  }
  public void run(){
   while(true){
     buffer.log(message);
     buffer.getContents();
   }
  }
  public static void main(String[] args) {
   StringBufferTest ss = new StringBufferTest();
   new RunThread(ss, "you").start();
   new RunThread(ss, "me").start();
   new RunThread(ss, "she").start();
  }
}

このコードは完全にスレッドセーフです。メソッド内で定義された変数は、各スレッドが入るときにこのローカル変数を作成します。スレッドの安全性の問題は関係ありません。一般に、システム セキュリティに関連する変数はメンバー変数です。stringBuffer 自体の内部実装はサイトセーフです。スレッド セーフとは、クラス自体が提供する関数が安全であることを意味します。つまり、文字列を挿入する場合、この文字列の挿入は安全ですが、2 つの文字列を挿入する必要があり、その間に他の挿入エラーが発生しても、2 つの文字列の順序を決定する必要があります。はい、独自のコードに問題があります。

読んでいただきありがとうございます、皆さんのお役に立てれば幸いです、このサイトをサポートしていただきありがとうございます!

Java コレクションのクラスに関するスレッド セーフティ関連の記事をさらに詳しく知りたい場合は、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。