2

私のテストプログラムは文字列を要求し、2秒ごとにそれを出力します。Javaメモリモデルについて、またはスレッドがメインメモリの変数をすぐに更新しない方法については、すでにいくつか読んだことがあります。

volatilestatic属性を試してみました。line変数が変更されたコードブロックを同期しています。wait()/notifi()変数が変更されたときと他のいくつか。値としてではなく参照として割り当てるにはどうすればよいlineですか?間違った方法を使用していますか?オブジェクトがモニターとして機能する場合は完全に同期を維持できるのに、ポインターとして機能する場合は同期できないのはなぜですか?

public class TestSharedVariable {
    static String line= "";

    public static void main(String[] args) {
        // For reading from keyboard
        Scanner keyboard = new Scanner(System.in);

        Printer p = new Printer(line);
        p.start();

        // Reads a line from keyboard into the shared variable
        while(!line.equals("quit")){
            line = keyboard.nextLine(); 

        }
    }
}

class Printer extends Thread{
    private volatile String line;

    public Printer(String palabra){
        this.line = palabra;
    }

    /*  Prints the line each 2 sec  */
    @Override
    public  void run(){
        while(!line.equals("quit")){
            try {
                sleep(2000);
            } catch (InterruptedException e) {e.printStackTrace();}
            System.out.println(this.getName() + ": " + line);
        }
    }
}

出力:

    Thread-0: 
    asdf
    Thread-0: 
    Thread-0: 
4

1 に答える 1

3

2つの主な問題があります。

  • 1つの文字列は不変であるため、作成された文字列変数を構成する文字など、文字列変数の状態を変更することはできません。
  • 同じオブジェクトに2つの参照変数を割り当てていますが、一方の変数の割り当てが変更された場合、一方の変数がその割り当てを変更することを期待しています。これは、Java参照変数の動作方法ではありません。

つまり、最初にPrinterオブジェクトの行変数をTestSharedVariableの静的行変数と同じ参照に設定している場合でも、後でTestSharedVariableの静的行変数の参照を変更しても、Printer行変数の参照割り当てには影響しません。これはスレッド化とは何の関係もなく、参照変数の理解と関係があります。Cまたは他の同様の言語のポインターのような参照変数を考えてみてください。2つの変数が同じオブジェクトを指している場合、1つの変数を別のオブジェクトを指すように変更しても、最初の変数には影響しません。

コードが機能するには、両方の変数が同じ可変オブジェクトへの参照を共有している必要があり、可変オブジェクトへの参照ではなく、可変オブジェクトの状態を変更する必要があります。

たとえば、

import java.util.Scanner;

public class TestSharedVariable {
   static volatile MutableObject mutableObject = new MutableObject();

   public static void main(String[] args) {
      // For reading from keyboard
      Scanner keyboard = new Scanner(System.in);

      Printer p = new Printer(mutableObject);
      new Thread(p, "Print thread").start();

      // Reads a line from keyboard into the shared variable
      while (!mutableObject.getData().equals("quit")) {
         mutableObject.setData(keyboard.nextLine());

      }
   }
}

class Printer implements Runnable {
   private volatile MutableObject mutableObject;

   public Printer(MutableObject mutableObject) {
      this.mutableObject = mutableObject;
   }

   /* Prints the line each 2 sec */
   @Override
   public void run() {
      while (!mutableObject.getData().equals("quit")) {
         try {
            Thread.sleep(2000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
         Thread thread = Thread.currentThread();
         System.out.println(thread.getName() + ": " + mutableObject);
      }
   }
}

class MutableObject {
   private String data = "";

   public String getData() {
      return data;
   }

   public void setData(String data) {
      this.data = data;
   }

   @Override
   public String toString() {
      return data;
   }

}
于 2013-03-27T02:34:28.640 に答える