5

Bu benim soruya bir takip olduğunu: Android thread runnable performanceAndroid senkronize edildiSensorChanged?

ben uygulamam için etrafında senkronize yöntemler başım sarma bazı zorluk yaşıyorum

ben taramayı sensörleri ve diziler içine sensör değerlerini saklamak kalsam onlar

float[] accelerometerMatrix = new float[3]; 
float[] accelerometerWorldMatrix = new float[3]; 
float[] gyroscopeMatrix = new float[3]; 
float[] gravityMatrix = new float[3]; 
float[] magneticMatrix = new float[3]; 
float[] rotationMatrix = new float[9]; 

class InsertHandler implements Runnable { 
     public void run() { 
      //get values from arrays and insert into db 
     } 
    } 

public void onSensorChanged(SensorEvent event) { 
     sensor = event.sensor; 

     int i = sensor.getType(); 
     if (i == MainActivity.TYPE_ACCELEROMETER) { 
      accelerometerMatrix = event.values; 
     } else if (i == MainActivity.TYPE_GYROSCOPE) { 
      gyroscopeMatrix = event.values; 
     } else if (i == MainActivity.TYPE_GRAVITY) { 
      gravityMatrix = event.values; 
     } else if (i == MainActivity.TYPE_MAGNETIC) { 
      magneticMatrix = event.values; 
     } 

     long curTime = System.currentTimeMillis(); 
     long diffTime = (curTime - lastUpdate); 

     // only allow one update every POLL_FREQUENCY. 
     if(diffTime > POLL_FREQUENCY) { 
      lastUpdate = curTime; 

      //insert into database in background thread 
      executor.execute(insertHandler); 
     } 
    } 

Her 10ms değiştirmek benim uygulaması (dizilerden) geçerli sensör değerleri alır ve tek bir iplik vasisi kullanarak bir veritabanına bunları ekler. Yani onSensorChanged yöntem iki dizide yazılı ve

Sorum, onSensorChanged yöntem

senkronize edilmelidir olduğu dizilerden okuma veritabanına yazmaktır?

En önemli şey, hiçbir veriyi kaçırmamam. Her 10 ms'de mevcut sensör değerlerini kaydetmem gerekiyor - hiçbiri kaçırılamaz.

Anlayışım gereği, senkronize edilmiş bir yöntem, UI iş parçacığının bir kilit tutacağı ve sensör değerlerini dizilere yazacağı anlamına gelir. Bu süre boyunca, yürütücü iplik kilidi nedeniyle bu dizilerden okuyamaz. Sonra kilit kaldırılır ve infaz iplik daha sonra kilitler, bültenleri

kilitlemek, dizilerden okur ve veritabanına yazma Özellikle onSensorChanged olay sürülür verildi ve emin değilim, burada senkronize yöntemlerin kullanımını yanlış anlama olabilir

bunun nasıl oynandığı

Fakat böyle bir durumda, her 10 ms'de en son değerleri eklemiyor olabilirim. UI iş parçacığı bir kilit oluşturduğunda, yürütücü iş parçacığı bu değerleri veritabanına yazamaz. Yürütücü iş parçacığı yazabildiği zaman, değerler şimdi birkaç ms eski ve hatalı

Diğer taraftan, eşitleme, UI iş parçacığının dizi değerlerini değiştirdiği durumlara sahip olmamam anlamına gelir. Aynı anda, yürütücü iş parçacığı, yarım değiştirilen değerleri veritabanına eklenir

Bu nedenle, her 10 ms'de bir en son/doğru algılayıcı verisini eklemek zorunda olduğum bir durum için, senkronize bir yöntem kullanmalı mıyım?

cevap

2

Geçerli kodunuz, Runnable'un UI iş parçacığının yazdığı dizileri aynı olduğundan emin olun. executor.execute(insertHandler);'u aradığınızda, UI iş parçacığının başka bir sensör olayı almaması ve Runnable'un bunları veritabanına yazmadan önce dizi değerlerinden birini değiştirmesi garanti değildir. Bu kısmı anladığın anlaşılıyor.

Bunu düzeltmek için, senkronize edilmiş bir blok kullanmanızı tavsiye etmiyorum, çünkü sadece diffTime > POLL_FREQUENCY numaralı dizilerde hangi değerlerin depolandığını yazıyorsunuz. Bu yöntemde ise Dizilerin değerini değiştirerek başka bir iş parçacığı konusunda endişelenmenize gerek kalmaz onSensorChanged(...) yöntem kendisi sadece hiç kodunuzda UI iş parçacığı üzerinde çağrılacak. Bütün bunlarla

ne yapmak edebilirsiniz Runnable sınıfın yeni bir örneğini diziler geçerli değerlerini saklamak olduğunu söyledi. Bunların aynı örneği kullanmak için önceki sonrası öne sürüldü biliyorum ama bu bir fark yapmaz. Android Monitor uygulamasını açıp, uygulamanızın çalışmasıyla bellek kullanımını kontrol ederek de doğrulayabilirsiniz.Mevcut değerleri saklayarak, artık yazdığınız veriyi yazmadan önce onSensorChanged()'un tekrar çağrılması sorun olmayacaktır, çünkü ihtiyacınız olan verilerin bir kopyası zaten değişmeyecektir.

class InsertHandler implements Runnable { 
    final float[] accelerometerMatrix; 
    final float[] accelerometerWorldMatrix; 
    final float[] gyroscopeMatrix; 
    final float[] gravityMatrix; 
    final float[] magneticMatrix; 
    final float[] rotationMatrix; 

    public InsertHandler(float[] accelerometerMatrix, float[] accelerometerWorldMatrix, 
      float[] gyroscopeMatrix, float[] gravityMatrix, 
      float[] magneticMatrix, float[] rotationMatrix) { 
     this.accelerometerMatrix = accelerometerMatrix; 
     this.accelerometerWorldMatrix = accelerometerWorldMatrix; 
     this.gyroscopeMatrix = gyroscopeMatrix; 
     this.gravityMatrix = gravityMatrix; 
     this.magneticMatrix = magneticMatrix; 
     this.rotationMatrix = rotationMatrix; 
    } 

    public void run() { 
     // use class field arrays values and insert into db 
    } 
} 

Ve sonra executor kullanımına Runnable eklerken:

Runnable insertHandler = new InsertHandler(accelerometerMatrix, accelerometerWorldMatrix, 
     gyroscopeMatrix, gravityMatrix, magneticMatrix, rotationMatrix); 
executor.execute(insertHandler); 
İşte

ben kodunda düşündüren am budur