2013-07-19 14 views
6

Sto cercando di accedere e modificare una variabile di un thread in un altro thread in java e davvero non so come farlo.Accesso a una variabile di un thread da un altro thread in java

es:

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

grazie se avete qualche idea!

C'è un modo per creare un getter e setter per un thread in java?

EDIT: le risposte sono state buone, ma non era chiaro nella mia interrogazione, cercherò di fare una domanda migliore

+0

I thread non hanno variabili. Le classi hanno membri e i metodi hanno parametri e variabili locali. Se riesegui l'analisi del problema seguendo queste linee, la risposta dovrebbe essere ovvia. – EJP

risposta

4

Si potrebbe fare una specie di lavoro ma, ti suggerisco di usare uno AtomicInteger che è condiviso tra i thread.

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

È possibile utilizzare AtomicReference per i riferimenti agli oggetti.

4

Creare un eseguibile, e utilizzare il setter e getter definiti in detto eseguibile.

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

Nota: la parola chiave volatile viene utilizzata qui. La parola chiave volatile assicura se questa stringa cambia in un thread, che tutti i thread vedranno la modifica. Se invece mi assicuro che l'unico accesso all'oggetto String sia attraverso il contesto sincronizzato, la parola chiave volatile non sarebbe necessaria.

Per dimostrare il mio punto, il codice precedente e il codice di seguito sono sia thread-safe, ma sono diversi come no 2 fili possono entrare setString e getString simultaneamente nell'esempio che segue.

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

Un thread è in realtà solo eseguendo una eseguibile. È possibile utilizzare questo modo:

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

Utilizzando valori atomici per primitive va bene, ma se mai desidera condividere un oggetto più complesso, si dovrà leggere su threading and synchronization.

Ad esempio:

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

Questo codice mostra un esempio di sincronizzazione con oggetti non primitivi tramite la parola chiave synchronized. L'utilizzo della parola chiave sincronizzata in una definizione di metodo blocca la classe utilizzando se stessa come oggetto di sincronizzazione.

Una nota finale, la parola chiave sincronizzata non viene solo utilizzata nelle definizioni dei metodi. Puoi usarlo per sincronizzare istanze all'interno dei metodi come ho fatto nel metodo run in StatRunnable.

+0

Potete fornire un esempio in un modo sicuro per i thread? Sembra il codice originale, ma con setter/getter e accesso diretto al campo. –

+0

Questo thread è sicuro poiché nulla tocca la stringa :) ma sì, scriverò un esempio più complesso. –

+0

AFAIK hai sostituito 'String myString = runnable.myString;' con 'String myString = runnable.getString();' che fa la stessa cosa. –