2013-07-19 12 views
6

Ich versuche, auf eine Variable eines Threads in einem anderen Thread in Java zuzugreifen und zu ändern, und ich weiß wirklich nicht, wie das geht.Auf eine Variable eines Threads von einem anderen Thread in Java zugreifen

ex:

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(); 

danken Ihnen, wenn Sie eine Idee haben!

Gibt es eine Möglichkeit, einen Getter und Setter für einen Thread in Java zu erstellen?

EDIT: die Antworten waren gut, aber ich war in meiner Frage nicht klar ist, werde ich versuchen, eine bessere Frage

+0

Threads haben keine Variablen. Klassen haben Mitglieder und Methoden haben Parameter und lokale Variablen. Wenn Sie Ihr Problem in dieser Richtung analysieren, sollte die Antwort offensichtlich sein. – EJP

Antwort

4

Sie könnten es Arbeit machen, aber ich schlage vor, Sie verwenden eine AtomicInteger, die zwischen Threads geteilt wird.

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

Sie können AtomicReference für Verweise auf Objekte verwenden.

4

erstellen runnable fragen, und verwenden Sie die Getter und Setter Sie definieren, die in runnable.

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

Hinweis volatile Schlüsselwort wird hier verwendet. Das flüchtige Schlüsselwort stellt sicher, dass sich diese Zeichenfolge in einem Thread ändert, sodass alle Threads die Änderung sehen. Wenn stattdessen sichergestellt wird, dass der einzige Zugriff auf das String-Objekt über einen synchronisierten Kontext erfolgt, ist das Schlüsselwort volatile nicht erforderlich.

Um meinen Punkt zu demonstrieren, sind der obige Code und der folgende Code beide Thread-sicher, aber sind unterschiedlich, da keine 2 Threads setString und getString simultan im folgenden Beispiel eingeben können.

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

Ein Thread ist wirklich nur Ausführen eines Runnable. Man könnte dies wie so verwenden:

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

für Primitive Atom Werten ist in Ordnung, aber wenn Sie jemals eine komplexere Aufgabe teilen möchten, werden Sie über threading and synchronization.

Zum Beispiel lesen:

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

Dieser Code zeigt ein Beispiel für die Synchronisation mit nicht primitiven Objekten über das Schlüsselwort synchronized. Die Verwendung des synchronisierten Schlüsselworts in einer Methodendefinition sperrt die Klasse, die sich selbst als Synchronisierungsobjekt verwendet.

Eine letzte Anmerkung, das synchronisierte Schlüsselwort wird nicht nur in Methodendefinitionen verwendet. Sie können es verwenden, um Instanzen innerhalb von Methoden wie in der run-Methode in StatRunnable zu synchronisieren.

+0

Können Sie ein Beispiel in einer thread-sicheren Weise bereitstellen? Dies sieht wie der Originalcode aus, aber mit Setter/Getter sowie direktem Zugriff auf das Feld. –

+0

Dies ist threadsicher, da nichts den String berührt :) aber ich schreibe ein komplexeres Beispiel. –

+0

AFAIK Sie haben 'String myString = runnable.myString;' mit 'String myString = runnable.getString(); ersetzt, was das gleiche tut. –

Verwandte Themen