2012-07-21 10 views
6

Nel mio programma Android un'attività chiama una nuova classe di visualizzazione di superficie, che a sua volta chiama una nuova classe thread. Voglio essere in grado di passare un valore alla classe thread dai metodi onPause e onResume dell'attività, così posso mettere in pausa e riprendere il thread. L'unico modo che conosco per passare questi dati è creare una nuova istanza, che creerebbe solo un thread diverso. Come devo andare su questo senza creare una nuova istanza di thread?Passaggio di un valore dall'attività al thread dopo che il thread è già stato creato

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(new GameSurface(this)); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
      //Would like to pass this value 
      int state = 1; 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
      //Would like to pass this value 
      int state = 2; 
} 
+0

Ho aggiornato la mia risposta con 2 classi e un'implementazione funzionante di "AtomicInteger". Saluti – Killrawr

risposta

4

Un po 'di storia sulla concorrenza

Passando valori nella concorrenza è la parte facile. Esaminare il tipo di dati AtomicInteger (Ulteriori informazioni here). Atomicità significa anche All or nothing. Questo tipo di dati non sta necessariamente inviando dati tra thread o processori (come con lo mpi) ma sta semplicemente condividendo i dati sulla sua memoria condivisa.

Ma ciò che è un'azione atomica? ....

Un'operazione atomica è un'operazione che viene eseguita come una singola unità di lavoro, senza la possibilità di interferenze da altre operazioni.

In Java la specifica del linguaggio garantisce che la lettura o la scrittura di una variabile sia atomica (a meno che la variabile non sia di tipo long o double). Lunga e doppio sono solo atomica se dichiarate come volatili ....

credito (Java Concurrency/Multithreading - Tutorial da Lars Vogel)

consiglio vivamente di leggere questo, che copre tutto, dai atomicity, thread pools, deadlocks e the "volatile" and "synchronized" keyword.


Inizio ClasseQuesto eseguirà un nuovo thread (Può anche essere indicato come il nostro Main Thread).

import java.util.concurrent.atomic.AtomicInteger; 
/** 
* @author Michael Jones 
* @description Main Thread 
*/ 
public class start { 
    private AtomicInteger state; 
    private Thread p; 
    private Thread r; 
    /** 
    * constructor 
    * initialize the declared threads 
    */ 
    public start(){ 
     //initialize the state 
     this.state = new AtomicInteger(0); 
     //initialize the threads r and p 
     this.r = new Thread(new action("resume", state)); 
     this.p = new Thread(new action("pause", state)); 
    } //close constructor 

    /** 
    * Start the threads 
    * @throws InterruptedException 
    */ 
    public void startThreads() throws InterruptedException{ 
     if(!this.r.isAlive()){ 
      r.start(); //start r 
     } 
     if(!this.p.isAlive()){ 
      Thread.sleep(1000); //wait a little (wait for r to update)... 
      p.start(); //start p 
     } 
    } //close startThreads 

    /** 
    * This method starts the main thread 
    * @param args 
    */ 
    public static void main(String[] args) { 
     //call the constructor of this class 
     start s = new start(); 
     //try the code 
     try { 
      s.startThreads(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } //start the threads 
    } //close main 

} //close class start 

Poiché il numero intero è atomico, è anche possibile recuperare ovunque, ma il main method nel Inizia Classe con System.out.println("[run start] current state is... "+state.intValue());. (Se si desidera recuperare dalla main method, si dovrà impostare un Setter/Getter, come ho fatto in Class Action)

Class ActionQuesta è la nostra discussione in azione (Può anche essere indicato come il nostro Slave Thread).

import java.lang.Thread.State; 
import java.util.concurrent.atomic.AtomicInteger; 

/** 
* @author Michael Jones 
* @description Slave Thread 
*/ 
public class action implements Runnable { 

    private String event = ""; 
    private AtomicInteger state; 

    /** 
    * The constructor (this represents the current instance of a thread). 
    * 
    * @param event 
    * @param state 
    */ 
    public action(String event, AtomicInteger state) { 
     this.event = event; // update this instance of event 
     this.state = state; // update this instance of state 
    } // constructor 

    /** 
    * This method will be called after YourThreadName.Start(); 
    */ 
    @Override 
    public void run() { 
     if (this.event == "resume") { 
      this.OnResume(); // call resume 
     } else { 
      this.OnPause(); // call pause 
     } 
    } // close Runnable run() method 

    /** 
    * The resume function Use the auto lock from synchronized 
    */ 
    public synchronized void OnResume() { 
     System.out.println("[OnResume] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(2); // change the state 
     System.out.println("[OnResume] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * The pause function Use the auto lock from synchronized 
    */ 
    public synchronized void OnPause() { 
     System.out.println("[OnPause] The state was.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
     this.setAtomicState(1); // change the state 
     System.out.println("[OnPause] The state is.." + this.getAtomicState() 
       + " // Thread: " + Thread.currentThread().getId()); 
    } // close function 

    /** 
    * Get the atomic integer from memory 
    * 
    * @return Integer 
    */ 
    private Integer getAtomicState() { 
     return state.intValue(); 
    }// close function 

    /** 
    * Update or Create a new atomic integer 
    * 
    * @param value 
    */ 
    private void setAtomicState(Integer value) { 
     if (this.state == null) { 
      state = new AtomicInteger(value); 
     } else 
      state.set(value); 
    } // close function 

} // close the class 

output La console

[OnResume] The state was..0 // Thread: 9 
[OnResume] The state is..2 // Thread: 9 
[OnPause] The state was..2 // Thread: 10 
[OnPause] The state is..1 // Thread: 10 

Come si può vedere, la AtomicInteger state è condiviso nella memoria tra le nostre discussioni r e p.


Solution e Cose da cercare ...

L'unica cosa che dovete guardare quando si fa la concorrenza è Race Conditions/Deadlocks/Livelocks. Alcuni RaceConditions si verificano perché Threads vengono creati in ordine casuale (e la maggior parte dei programmatori pensa nella sequenza mentale di ordine sequenziale).

ho la linea Thread.sleep(1000); modo che il mio Main Thread dà il filo schiavo r un po 'di tempo per aggiornare il state (prima di consentire p per eseguire), causa del ordine casuale di fili.

1) Mantenere un riferimento al thread e passare il valore con un metodo. credito (SJuan76, 2012)

Nella soluzione che ho postato io faccio il mio Main Thread (aka class start) come il mio comunicatore principale per tenere traccia del Atomic Integer per i miei schiavi da utilizzare (aka class action). Il thread principale è anche updating il memory buffer per il Atomic Integer per i miei slave (L'aggiornamento sul buffer di memoria si verifica sullo sfondo dell'applicazione ed è gestito dalla classe AtomicInteger).

+0

Grazie. Quindi devo usare un costruttore o un metodo AtomicInteger nella classe thread per ottenere lo stato aggiornato? Scusa se non è giusto. Java è piuttosto nuovo per me. – zkello

+0

Devi usare la dichiarazione AtomicInteger in ogni classe (diciamo che ho una classe 'foo' che crea un thread con la classe' boo') Avrei bisogno del mio 'AtomicInteger x' dichiarato in entrambe le classi in modo che fosse condiviso attraverso la memoria. – Killrawr

+0

Aggiungete anche 'synchronized' al vostro' onPause() 'e' onResume() ', per esempio' protected synchronized void onResume() '. Ciò abilita il blocco automatico del thread o della variabile 'state'. Ed eviterà una possibile "condizione di gara". Cordiali saluti – Killrawr

3

1) Mantenere un riferimento al thread e passare il valore con un metodo.

2) Durante la creazione del thread, passarlo un oggetto condiviso con l'attività. Metti i valori da passare nell'oggetto, fai controllare il thread regolarmente fino a quando i valori non vengono trovati.

+0

la prima soluzione non potrebbe causare condizioni di gara possibili? se "onResume' o' onPause' si affidano l'un l'altro? – Killrawr

1

Io uso la classe di riferimento che io chiamo Share Class. Ha la variabile con il tipo volatile.

volatili viene usato per indicare che il valore di una variabile sarà modificata da diversi fili.

public class Share { 
    public static volatile type M_shared; 
} 

per cambiare questa variabile, si dovrebbe bloccarlo e dopo il cambiamento del valore, rilasciare il blocco. È possibile leggere e scrivere utilizzando Share.M_shared.

Problemi correlati