10

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でスレッドのゲッターとセッターを作成する方法はありますか?

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

4

2 に答える 2

7

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

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(){}
}

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

私の要点を示すために、上記のコードと以下のコードは両方ともスレッドセーフですが、以下の例では2つのスレッドが同時に入ることができないため、異なりsetStringますgetString

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 キーワードはメソッド定義だけで使用されるわけではありません。runのメソッドで行ったように、これを使用してメソッド内のインスタンスを同期できますStatRunnable

于 2013-07-19T22:13:44.970 に答える
7

ある程度機能させることもできますが、スレッド間で共有される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 を使用できます。

于 2013-07-19T22:14:22.097 に答える