それをひっくり返さないでください、マルチスレッドでのメンバー変数とローカル変数の使用、この記事を読むだけで十分です

1. メンバ変数とローカル変数の違い

  1. クラス内のさまざまな位置
    メンバー変数: クラス内のメソッドの外側
    ローカル変数: メソッドまたはコード ブロック内、またはメソッドの宣言上 (つまり、パラメーター リスト内)
  2. メモリ上の異なる場所
    メンバ変数: ヒープ(メソッド領域内の静的領域)内で、メンバ変数はオブジェクトに属し、オブジェクトはヒープに格納されます
    ローカル変数: スタック内では、ローカル変数はメソッドに属し、メソッドはヒープに格納されますスタックメモリ
  3. さまざまなライフサイクル
    メンバー変数: オブジェクトの作成とともに存在し、オブジェクトの消滅とともに消滅します。
    ローカル変数: メソッドの呼び出しまたはコード ブロックの実行とともに存在し、メソッド呼び出しまたはコード ブロックの実行の完了とともに消滅します。コードブロックの実行が消える
  4. 初期値
    メンバー変数: デフォルトの初期値あり
    ローカル変数: デフォルトの初期値なし、使用前に割り当てる必要があります
  5. 注:
    メンバー変数とローカル変数の間で名前が重複する問題は、近接性の原理に基づいています。区別する
    には this キーワードを使用できます。this.string はメソッド内ではなくクラス内のメンバー変数を参照します。

コード例:

public class test {
    
    
    public static void main(String[] args) {
    
    
        int a = 3;          // 这个是成员变量
        Thread thread = new Thread(() -> {
    
    
            int b = 4;      // 这是一个局部变量
        });
        thread.start();
    }
}

2.マルチスレッドで呼び出しメンバー変数を変更する


2 つ以上のスレッドがオブジェクトのメンバー変数にアクセスする場合、メンバー変数はオブジェクトに属しているため、2 つのスレッドは 1 つのメンバー変数を共有します。つまり、スレッドがメンバー変数の値を変更すると、その変更は次のオブジェクトに影響を与えます。他のスレッド。

メンバー変数を使用する必要がある場合は、変数を静的な静的な値または AtomicInteger アトミック値に設定できますが、これにより混乱が生じます。静的な型を例に挙げます。

public class test {
    
    
    static int i = 0;
    public static void main(String[] args) throws Exception {
    
    
        Thread thread1 = new Thread(() -> {
    
    
            for (i = 0; i < 50; i++) {
    
    
                System.out.print(i + " ");
            }
        });
        thread1.start();

        Thread thread2 = new Thread(() -> {
    
    
            for (i = 0; i < 50; i++) {
    
    
                System.out.print(i + " ");
            }
        });
        thread2.start();
    }
}

输出:
0 1 2 3 4 5 6 1 1 3 4 5 6 7 2 8 10 11 12 13 14 15 9 17 18 19 16 20 22
23 21 25 26 27 28 29 30 31 32 33 34 35 36 24 38 39 40 41 42 43 44 45 
46 37 48 49 47

0 ~ 50 の数字が 2 回出力されるべきであることがわかりましたが、その結果の出力は文字化けでした。これは、マルチスレッドでは、スレッドによるメンバー変数の呼び出しと変更が他のスレッドに影響を与えるという私たちの観点も検証しました。

もちろん、メンバー変数を呼び出すだけで変更しない場合は可能です。コードは以下のように表示されます。

public class test {
    
    
    public static void main(String[] args) throws Exception {
    
    
        int i = 50;
        Thread thread1 = new Thread(() -> {
    
    
            for (int i1 = 0; i1 < i; i1++) {
    
    
                System.out.print(i1 + " ");
            }
        });
        thread1.start();

        Thread thread2 = new Thread(() -> {
    
    
            for (int i1 = 0; i1 < i; i1++) {
    
    
                System.out.print(i1 + " ");
            }
        });
        thread2.start();
    }
}

输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0 17 18 1 2 3 4 5 6 7 8 9 10
11 19 12 13 14 15 16 17 18 19 20 20 21 22 23 24 25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 

0 ~ 50 の順不同の配列が 2 回出力されることがわかりますが、これは実現可能です。

他のスレッドの影響を受けずにメンバー変数を呼び出して変更する方法はありますか?


複数のメンバ変数を代入して静的型やAtoimcInteger型に変更することで、複数のメンバ変数を異なるアドレスに格納し、各スレッドで異なるメンバ変数を呼び出すことができます。例として AtomicInteger 型のメンバー変数を取り上げます。コードは次のとおりです。

public class test {
    
    
    public static void main(String[] args) throws Exception {
    
    
        int i = 50;

        AtomicInteger i1 = new AtomicInteger(i);
        Thread thread1 = new Thread(() -> {
    
    
            for (i1.set(0); i1.get() < 50; i1.getAndIncrement()) {
    
    
                System.out.print(i1 + " ");
            }
        });
        thread1.start();

        AtomicInteger i2 = new AtomicInteger(i);
        Thread thread2 = new Thread(() -> {
    
    
            for (i2.set(0); i2.get() < 50; i2.getAndIncrement()) {
    
    
                System.out.print(i2 + " ");
            }
        });
        thread2.start();
    }
}

结果:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 16 1 2 17 18 3 4 19 20 5 6 7 8
9 10 11 12 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 13 37 38 39 
14 15 16 17 18 19 40 20 41 21 22 23 24 25 26 27 28 29 42 30 31 43 44 45 
46 47 48 32 33 34 49 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 

0 ~ 50 の順不同の配列が 2 回出力されることがわかりますが、これは実現可能です。

したがって、マルチスレッド環境でメンバー変数を呼び出して変更したい場合は、メンバー変数のコピーを複数作成し、それらを静的型または AtoimcInteger 型に変更し、呼び出すだけでよいと結論付けることができます。

3. マルチスレッドでローカル変数を変更して呼び出す


各ローカル変数は各スレッドに対してプライベートであるため、他のスレッドに影響を与えることなく直接変更できます。コードは以下のように表示されます。

public class test {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Thread thread1 = new Thread(() -> {
    
    
            int i = 0;
            for (i = 0; i < 50; i++) {
    
    
                System.out.println(i + " ");
            }
        });
        thread1.start();

        Thread thread2 = new Thread(() -> {
    
    
            int i = 0;
            for (i = 0; i < 50; i++) {
    
    
                System.out.println(i + " ");
            }
        });
        thread2.start();
    }
}

输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 0 1 2 3 4 5 
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 41 42 43 23 44 24 25 45 46 47 26 48 49 27 
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 

0 ~ 50 の順不同の配列が 2 回出力されることがわかりますが、これは実現可能です。

おすすめ

転載: blog.csdn.net/weixin_43899069/article/details/121973745