2017-08-19 8 views
2

変数varの値は常に0です。ITは、メソッドが呼び出されなかったかのようになります。スレッドの内部からvalの値を変更できるようにしたいと思います.getVal()を呼び出すと、新しい値にアクセスできるようにしたいと考えています。Javaオブジェクトの属性をスレッドから更新しますか?

public class Test1 { 
    private int val; 

    public Test1() { 
     val=0; 
    } 

    public void changeVal() { 

     new Thread(new Runnable() { 
      public void run() { 
       val=1; 
      } 
     }).start(); 
    } 

    public int getVal() { 
     return this.val; 
    } 

    public static void main(String[]args) { 
     Test1 x=new Test1(); 
     x.changeVal(); 
     System.out.println("VAl: "+x.getVal()); 
    } 
} 
+3

値を印刷する前にスレッドの開始/完了を待つ必要があるかもしれません。 [Thread.join()](https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()) –

+0

'メソッドが呼び出されなかったかのようです'これは、コードが正しく同期されていない場合にスレッド間の可視性がどのように失敗するかについての非常に正確な記述です。 – biziclop

答えて

0

あなたの声明

x.changeVal(); 

System.out.println("VAL: "+x.getVal()); 

間の競合状態が上記の二つの文の間に次のコードを入れてみてください設定しています。

try { 
     Thread.sleep(100); 
    } 
    catch (Exception e) { 
     System.out.println("Exception: " + e); 
    } 

これはあなたの新しいスレッドあなたがのprintln文を達する前に確立する機会を与えてくれます。

+0

チャンスはありますが保証はありません。 – biziclop

3

値は変更されますが、getVal()はメソッド 'run'のvar = 1より前に(ほとんどの場合)実行されます。実行順序はスレッドスケジューラによって制御されますが、Johnny Moppの説明によると、.join()を追加すると修正されます。

public void changeVal() throws InterruptedException { 
     Thread t = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       val = 1; 

      } 

     }); 
     t.start(); 
     t.join(); 

    } 

    public static void main(String[] args) throws InterruptedException { 
     Test1 x = new Test1(); 
     x.changeVal(); 

     System.out.println("VAl: " + x.getVal()); 
    } 
+0

あなたのコードが効果的にシングルスレッド化されているので、これが本質的に別のスレッドの必要性をどのように否定するかを、 – biziclop

+0

同意すると、別のスレッドを使用する必要はありませんが、これを並行処理の練習として考えてみましょう –

0

あなたは以下のようなあなたの主な方法を変更する必要があります。

public static void main(String[]args) 
{ 
    Test1 x=new Test1(); 
    x.changeVal(); 
    try { 
     Thread.sleep(100);//sometime here 
    } 
    catch (Exception e) { 
     System.out.println("Exception: " + e); 
    } 
    System.out.println("VAl: "+x.getVal()); 

} 

それとも

あなたはchangeVal()方法で子スレッドとメインスレッドに参加するThread.join();を使用することができます。

0

一つsoultionはReentrantLockのの使用

、あなたが変数volatileを行う必要がありchangeVal

public void changeVal() throws InterruptedException { 
    if (lock.tryLock()) { 
     try { 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        val = val + 1; 
       } 
      }).start(); 

     } finally { 
      lock.unlock(); 
     } 
    } 

} 
-1

にこのロックを使用し

Lock lock = new ReentrantLock(); 

クラスのメンバ変数として定義することができ変数を変更したい場合は、同期やロックを調整する必要があります主な方法でそれを印刷します。スレッドを完全に無意味にする。

本当にそれのいずれかのポイントを参照してください。

関連する問題