2012-09-25 19 views
5

Intro:Comunicazione multithread: quanto è buono l'uso di variabili atomiche come AtomicInteger? perché non c'è AtomicFloat?

Voglio creare un'app Android multithread. Il mio problema è la comunicazione tra i thread. Ho letto della comunicazione tra i thread e mi sono imbattuto in cose come Looper/Handler design, che sembrava abbastanza complicato e Variabili Atomiche come AtomicInteger. Per ora, ho usato AtomicInteger come comunicazione, ma dal momento che non ho molta esperienza in Java, non sono sicuro che nel mio caso non funzioni bene/se c'è una soluzione migliore per il mio scopo particolare. Inoltre ho avuto un po 'di sospetto sul mio metodo, quando ho notato che ho bisogno di qualcosa come AtomicFloat, ma non esiste. Mi sentivo come se mi mancasse il concetto. Ho anche scoperto che puoi farti un AtomicFloat, ma non sono sicuro se sono sulla strada giusta o se c'è una tecnica migliore.

Domanda: Va bene/usare le variabili atomiche e implementare anche AtomicFloat per il mio particolare scopo (descritto di seguito) o esiste un modo migliore di gestire la comunicazione?

Scopo/Architettura di App usando AtomicVariables finora:

Ho 4 discussioni con le seguenti finalità:

1.SensorThread: Legge i dati del sensore e salva i valori più recenti in AtomicVariables come

AtomicFloat gyro_z,AtomicFloat gyro_y, ... 

2.CommunicationThread: comunicazione con il PC, interpreta i comandi che vengono formare la presa e impostare lo stato dell'applicazione in termini of a AtomicInteger: AtomicInteger state;

3.UIThread: visualizza i valori dei sensori di corrente da AtomicFloat gyro_z, AtomicFloat gyro_y,

4.ComputationThread: utilizza valori sensore AtomicFloat gyro_z,AtomicFloat gyro_y, ... e stato AtomicInteger state per eseguire calcoli e inviare comandi tramite USB.

+0

Sembra che si possa fare con un galleggiante volatile. – assylias

+0

Si prega di dare un'occhiata a questo post: http://stackoverflow.com/questions/5505460/java-is-there-no-atomicfloat-or-atomicdouble –

+0

@Perroloco ho letto che, ma i più bassi due risposte dicevano che si usa quello veramente raro. A me sembrava logico che AtomicFloat dovesse esistere. questo perché ho messo in discussione il mio uso di loro –

risposta

1

Hai sostanzialmente a lettori scrittori prob lem, con due lettori e (per il momento) solo uno scrittore. Se vuoi semplicemente passare tipi semplici tra i thread, un AtomicInteger o un AtomicFloat implementato in modo simile andrà bene.

Tuttavia, una soluzione più accomodante, che permetterebbe di lavorare con tipi di dati più complessi sarebbe un ReadWriteLock proteggere il codice in cui si leggere o scrivere i dati oggetto:

esempio:

private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //the reentrant impl 

.... 

public void readMethod() { 

    readWriteLock.readLock().lock(); 

    try { 
     //code that simply _reads_ your object 
    } finally { 
     readWriteLock.readLock().unlock(); 
    } 

} 

public void writeMethod() { 

    readWriteLock.writeLock().lock(); 

    try { 
     //... code that modifies your shared object/objects 
    } finally { 
     readWriteLock.writeLock().unlock(); 
    } 
} 

Ciò consentirà solo scenari "uno scrittore solo" o "lettore multiplo" per l'accesso ai tuoi oggetti condivisi.

Ciò consentirebbe ad esempio di lavorare con un tipo complesso che assomiglia a questo:

public class SensorRead { 

    public java.util.Date dateTimeForSample; 

    public float value; 

} 

Durante l'utilizzo di questo tipo di dati si dovrebbe cura se i due campi sono impostati e modificati in modo sicuro e in modo atomico. Gli oggetti di tipo AtomicXXX non sono più utili.

+0

grazie, immagino di poter rispettare il mio piano variabile Atomic. –

0

Devi prima chiediti se hai veramente bisogno della funzionalità di un teorico AtomicFloat. L'unico vantaggio che si potrebbe avere su un semplice volatile float è compareAndSet e sulle operazioni addAndGet (poiché suppongo che l'incremento e il decremento non abbiano realmente senso nel caso dei float).

Se davvero bisogno di quelli, probabilmente si potrebbe implementarli studiando il codice di esempio AtomicInteger:

public final int addAndGet(int delta) { 
    for (;;) { 
     int current = get(); 
     int next = current + delta; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 

Ora l'unico problema qui è che compareAndSet utilizza le chiamate specifiche della piattaforma che non esistono per i galleggianti , quindi avrete probabilmente bisogno di emulare utilizzando il metodo Float.floatToIntBits per ottenere un int, quindi utilizzare il CAS di AtomicInteger, qualcosa come:

private volatile float value; 

public final boolean compareAndSet(float expect, float next) { 
    AtomicInteger local = new AtomicInteger(); 
    for(;;) { 
     local.set(Float.floatToIntBits(value)); 
     if(local.compareAndSet(Float.floatToIntBits(expect), 
           Float.floatToIntBits(next)) { 
      set(Float.intBitsToFloat(local.get())); 
      return true; 
     } 
    } 
} 

public final float addAndGet(float delta) { 
    for (;;) { 
     float current = get(); 
     float next = current + delta; 
     if (compareAndSet(current, next)) 
      return next; 
    } 
} 
Problemi correlati