34

次のように、複数のスレッド間で変数を共有したいと思います。

boolean flag = true;
T1 main = new T1();
T2 help = new T2();
main.start();
help.start();

メインスレッドとヘルプスレッドの間で共有したいと思いflagます。これらは、私が作成した2つの異なるJavaクラスです。これを行う方法はありますか?ありがとう!

4

7 に答える 7

38

とは両方ともT1T2この変数を含むクラスを参照できます。
次に、この変数を揮発性にすることができます。これは、その変数への変更が両方のスレッドですぐに表示されることを意味します。

詳細については、この記事を参照してください。

揮発性変数は、同期された可視性機能を共有しますが、原子性機能は共有しません。これは、スレッドが揮発性変数の最新の値を自動的に確認することを意味します。これらはスレッドセーフを提供するために使用できますが、非常に制限された一連のケースでのみ使用できます。複数の変数間、または変数の現在の値と将来の値の間に制約を課さない場合です。

volatileまた、状態を共有するためのより複雑な手段と使用の長所/短所に注意してください。

于 2012-11-27T10:41:55.917 に答える
19

他の提案に加えて、フラグをコントロールクラスでラップし、親クラスでその最終インスタンスを作成することもできます。

public class Test {
  class Control {
    public volatile boolean flag = false;
  }
  final Control control = new Control();

  class T1 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  class T2 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  private void test() {
    T1 main = new T1();
    T2 help = new T2();

    new Thread(main).start();
    new Thread(help).start();
  }

  public static void main(String[] args) throws InterruptedException {
    try {
      Test test = new Test();
      test.test();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
于 2012-11-27T11:14:41.117 に答える
7

使用しても問題は解決しstaticません。

変数を使用synchronizeすると、別のスレッドで使用されているときに変数がロックされます。

volatileすべてのスレッド間で変数を最新の状態に保つには、keywordを使用する必要があります。

volatileの使用は、クラススレッドを安全にするもう1つの方法(同期されたアトミックラッパーなど)です。スレッドセーフとは、メソッドまたはクラスインスタンスを複数のスレッドで同時に問題なく使用できることを意味します。

于 2018-10-15T08:47:10.680 に答える
6

のインスタンス間で表示T1できるT2ようにするには、2つのクラスに変数を含むオブジェクトへの参照を含めることができます。

スレッドの実行中に変数を変更する場合は、同期を考慮する必要があります。最善のアプローチは正確な要件によって異なりますが、主なオプションは次のとおりです。

  • 変数を作成しますvolatile;
  • それをAtomicBoolean;に変えてください
  • それを使用するコードの周りで本格的な同期を使用します。
于 2012-11-27T10:43:33.250 に答える
5
  1. 静的にすると、この問題が修正される可能性があります。
  2. 他のスレッドのメインスレッドへの参照とその変数の表示
于 2012-11-27T10:42:46.150 に答える
2

ロック変数「a」と「b」を使用してそれらを同期し、「クリティカルセクション」を逆の順序でロックすることができます。例えば。「a」に通知してから「b」をロックし、「PRINT」、「b」に通知してから「a」をロックします。

以下のコードを参照してください:

public class EvenOdd {

    static int a = 0;

    public static void main(String[] args) {

        EvenOdd eo = new EvenOdd();

        A aobj = eo.new A();
        B bobj = eo.new B();

        aobj.a = Lock.lock1;
        aobj.b = Lock.lock2;

        bobj.a = Lock.lock2;
        bobj.b = Lock.lock1;

        Thread t1 = new Thread(aobj);
        Thread t2 = new Thread(bobj);

        t1.start();
        t2.start();
    }

    static class Lock {
        final static Object lock1 = new Object();
        final static Object lock2 = new Object();
    }

    class A implements Runnable {

        Object a;
        Object b;

        public void run() {
            while (EvenOdd.a < 10) {
                try {
                    System.out.println(++EvenOdd.a + " A ");
                    synchronized (a) {
                        a.notify();
                    }
                    synchronized (b) {
                        b.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    class B implements Runnable {

        Object a;
        Object b;

        public void run() {
            while (EvenOdd.a < 10) {

                try {
                    synchronized (b) {
                        b.wait();
                        System.out.println(++EvenOdd.a + " B ");
                    }
                    synchronized (a) {
                        a.notify();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力:

1 A 
2 B 
3 A 
4 B 
5 A 
6 B 
7 A 
8 B 
9 A 
10 B 
于 2017-12-30T16:08:49.140 に答える
0
于 2021-01-05T06:49:22.600 に答える