JUC同時実行シリーズ(4):[インタビューのよくある質問] ArrayListの非スレッドセーフティを解決するさまざまな方法、CopyOnWriteArrayListの詳細(コード例)

プログラムを実行することは難しくありません;難しいのはプログラムがどこまで実行できるかです!-激しい種子

ここに画像の説明を挿入
JUC同時実行シリーズ

JUC同時実行シリーズ(1):何ですか?並行性と並列
JUC並行性シリーズ(2)を混同していると聞きました。JUC並行性シリーズをウェイクアップするための正確な通知を達成するための条件の詳細な説明
(3):インタビューでの並行性、ロックについて尋ねられると、驚かされます。 )

1つは、ArrayListはスレッドセーフではない

以前のマルチスレッドシリーズでは、ArrayListはマルチスレッド環境では安全ではないと述べました。

詳細なマルチスレッド10:異なるケースからのみ、マルチスレッドの不安定性を深く理解して、より適切に解決できます

これまでに見たことがない場合でもかまいません。コードを取り出して確認してみましょう。

1.1 ArrayListのスレッドセーフでないコードの例

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
    
    
            new Thread(() -> {
    
    
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

演算結果

コレクションの長さに追加された数が、予想した長さではないことがわかります。

代わりに、上書きが発生する可能性があります。

ArrayListを複数のスレッドで収集することは安全ではありません。

ここに画像の説明を挿入

2つ目は、VectorがArrayList非スレッドセーフを解決する

Vectorがスレッドセーフであるだけでなく、ArrayListがListインターフェースから取得されるため、ここでVectorがここで言及されているのはなぜですか?もちろん一般的に使用されるのは、あなたがぼかしたインタビューの回答でもあります。

しかし、しかし...

ベクターしか知らない場合は、それだけでは不十分です。なぜそれを言うのですか?ほんの少しの質問です!

ArrayListはJDKまたはVectorで最初に登場したと思いますか?

答えは、最初にArrayListで、次にVectorでなければなりません。それでも疑問があります。Vectorは、ArrayListの非スレッド化問題を解決するためのものではありません。

しかし、答えは逆であってもよい。Vectorが追加されましたJDK1.0ながら、ArrayListには JDK1.2で追加されました。そのためVectorは古く、ArrayListは新しいものです(もちろん1.2は新しいものではありません)。

ここに画像の説明を挿入
ここに画像の説明を挿入

2.1ベクターがArrayList非スレッドコードの例を解く

Vectorの解法は非常に簡単で、ArrayListキーワードをVectorに置き換えるだけです。

 Vector<String> list = new Vector<String>();

ベクトル以外

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        Vector<String> list = new Vector<String>();
        for (int i = 0; i < 10000; i++) {
    
    
            new Thread(() -> {
    
    
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

演算結果
ここに画像の説明を挿入

2.2ベクトルは良いですが、注意して使用してください

Vectorはスレッドセーフリストですが、そのスレッドセーフな実装は、すべての操作にsynchronizedキーワードを追加することです。この方法は効率に重大な影響を与えるため、Vectoは推奨されません。

ここに画像の説明を挿入

2.3インタビューのベクターへの回答はボーナスアイテムではなく、単なる回答です

慎重に使用することに加えて、インタビューで会うときに、Vectorに答えるだけでは、Vectorは古いキーワードであり、答えと見なすことができるだけなので、実際には余分なポイントを与えることはありません。

しかし、Vectorに答えることができ、次の解決策を言うことができれば、知識の幅を反映できます。

3、synchronizedListはArrayList非スレッドセーフを解決します

synchronizedListは、Collectionsによって提供されるメソッドであり、解決も非常に簡単です。

List<String> list = Collections.synchronizedList(new ArrayList());

3.1 SynchronizedListがArrayList非スレッド化コード例を解決する

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        List<String> list = Collections.synchronizedList(new ArrayList());
        for (int i = 0; i < 10000; i++) {
    
    
            new Thread(() -> {
    
    
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

演算結果
ここに画像の説明を挿入

3.2 synchronizedListの長所と短所

synchronizedListの書き込み操作のパフォーマンスは、マルチスレッド操作で以下説明するCopyOnWriteArrayListよりもはるかに優れていますが、読み取り操作では同期キーワードを使用するため、CopyOnWriteArrayListよりも読み取りの方が優れています。

同期する場所、つまりロックする場所がある限り、もちろん、パフォーマンスの点でそれを行う良い方法はありません。

したがって、最善の方法はなく、最も適切なアプリケーションシナリオのみが存在します。

4、CopyOnWriteArrayList

CopyOnWriteArrayListは、主にコンピュータプログラミングの最適化戦略であるCopyOnWriteコピーオンライト(略してCOW)にあります。

コピーオンライトの考え方は、複数のスレッドが同時に同じリソースを読み取るとき、それらは一緒にポインターによってポイントされたリソースを取得しますが、いくつかのスレッドが同じリソースを操作(変更)するとき、実際にはコピーを作成しますが、他のスレッドは初期リソースへのスレッドアクセスは変更されません。

簡単に理解できるのは、データの書き込み時に問題が発生したときに上書き回避することです。

4.1 CopyOnWriteArrayListがArrayList非スレッドコード例を解決する

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 10000; i++) {
    
    
            new Thread(() -> {
    
    
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

演算結果
ここに画像の説明を挿入

4.2サマリーCopyOnWriteArrayList

上記に基づいて、私はあなたがCopyOnWriteArrayListを要約することができると思います。CopyOnWriteArrayListは、読み取りにおいてVectorおよび同期リストより優れていますが、その読み取りおよび書き込みパフォーマンスは、同期リストほど良くありません。

いよいよファイブ

最後に、より良い読書体験をするために、私が言いたいことすべてを以下に示します。

私は 私の意志に基づいた決定の種であり私がブログに書いたものは同じ信条
であった深刻な共有です。このブログ投稿を読むことができれば、それは私たちがまだ非常に運命にあることを意味します。私はそれがあなたにいくつかの助けをもたらすことを願っています、作成は簡単ではありません、私の記事の知識を取り除き、あなたの3つの連続した休暇、コメント、フォローなど、私の最大の動機です。

おすすめ

転載: blog.csdn.net/A_hxy/article/details/108704234