web-dev-qa-db-ja.com

java)の別のスレッドからスレッドの変数にアクセスする

Javaの別のスレッドでスレッドの変数にアクセスして変更しようとしていますが、これを行う方法が本当にわかりません。

例:

Runnable r1 = new Runnable() {
    int value = 10;
    public void run() {
        // random stuff
    }
}
Runnable r2 = new Runnable() {
   public void run() {
        // of course the bellow line will not work
        r1.value--; // I want here to be able to decrement the variable "value" of r1
    }
}
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();

何かアイデアがあればありがとう!

Javaでスレッドのゲッターとセッターを作成する方法はありますか?

編集:答えは良かったが、私は私の質問で明確ではなかった、私はより良い質問をしようとします

9

一種の作業にすることもできますが、スレッド間で共有される AtomicInteger を使用することをお勧めします。

final AtomicInteger value = new AtomicInteger(10);
Runnable r1 = new Runnable() {
    public void run() {
        // random stuff using value
    }
}
Runnable r2 = new Runnable() {
   public void run() {
        value.decrementAndGet();
    }
}

オブジェクトへの参照にはAtomicReferenceを使用できます。

5
Peter Lawrey

ランナブルを作成し、そのランナブルで定義したセッターとゲッターを使用します。

public class MyRunnable implements Runnable{
    private volatile String myString;
    public String setString(String value){this.myString = value;}
    public String getString(){
        return myString;
    }
    public void run(){}
}

ここではvolatileキーワードが使用されていることに注意してください。 volatileキーワードは、この文字列が1つのスレッドで変更された場合に、すべてのスレッドが変更を確認できるようにします。代わりに、Stringオブジェクトへの唯一のアクセスが同期されたコンテキストを介することを確認した場合、volatileキーワードは必要ありません。

私の主張を示すために、上記のコードと以下のコードはどちらもスレッドセーフですが、以下の例では2つのスレッドがsetStringgetStringに同時に入ることができないため異なります。

public class MyRunnable implements Runnable{
    private String myString;
    public synchronized String setString(String value){this.myString = value;}
    public synchronized String getString(){
        return myString;
    }
    public void run(){}
}

スレッドは実際には実行可能ファイルを実行しているだけです。あなたは次のようにこれを使うことができます:

MyRunnable runnable = new MyRunnable();
Thread myThread = new Thread(runnable);
myThread.start();
String myString = runnable.getString();

プリミティブにアトミック値を使用することは問題ありませんが、より複雑なオブジェクトを共有したい場合は、 スレッド化と同期について読む必要があります。

例えば:

public class Stats{
    int iterations;
    long runtime;
    public Stats(){
        iterations = 0;
        runtime=0;
    }
    public synchronized void setIterations(int value){this.iterations = value;}
    public synchronized void setRuntime(long milliseconds){
        this.runtime = milliseconds;
    }
    public synchronized int getIterations(){
         return iterations;
    }
    public synchronized long getRuntime(){return runtime;}
}

public class StatRunnable implements Runnable{
    Stats stats;
    boolean active;
    public StatRunnable(){
        this.active=true;
    }
    public Stats getStats(){
        return stats;
    }
    long calculateRuntime(){return 0L;}
    public void run(){
        while(active){
            //i'm synchronizing with stats to ensure no other thread alters values
            //simultaneously.
            synchronized(stats){
                stats.setIterations(stats.getIterations()+1);
                stats.setRuntime(calculateRuntime());
            }
        }
    }
}

このコードは、synchronizedキーワードを介した非プリミティブオブジェクトとの同期の例を示しています。メソッド定義でsynchronizedキーワードを使用すると、それ自体を同期オブジェクトとして使用してクラスがロックされます。

最後に、synchronizedキーワードはメソッド定義で使用されるだけではありません。 runStatRunnableメソッドで行ったように、メソッド内のインスタンスで同期するために使用できます。

4