Android synced onSensorChanged?

This is a question about my next question: Performance for Android threads

I am having difficulty moving my head around synchronized methods for my application.

I check sensors and store sensor values ​​in arrays when they change

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

Every 10 ms, my application will take the current sensor values ​​(from arrays) and insert them into the database using one stream executor. Thus, the onSensorChanged method writes to arrays and reads from arrays for writing to the database

My question is should the onSensorChanged method be synchronized?

Most importantly, I do not miss any data. Every 10 ms I need to save the current sensor values ​​- no one can be skipped.

So, in my opinion, a synchronized method means that the user interface thread will contain a lock and it will write sensor values ​​to arrays. During this time, the stream of executors cannot read from these arrays due to blocking. Then the lock rises, and the stream of executors is then blocked, read from arrays and written to the database, releases the lock

Perhaps I misunderstand the use of synchronized methods, especially considering that onSensorChanged is event driven, and I'm not sure how this happens in it

But it seems that in such a situation, I could not insert the most recent values ​​every 10 ms. When the user interface thread sets a lock, the worker thread cannot write these values ​​to the database. By the time the stream of artists can be recorded, the values ​​will now have a few ms old and inaccurate

On the other hand, synchronization will mean that I have no situations where the user interface thread changes the values ​​of the array, while the worker thread inserts half of the changed values ​​into the database

So, for this type of situation where I need to insert the most recent / accurate sensor data every 10 ms, should I use the synchronous method?

+5
source share
1 answer

Your current code is not thread safe, as Runnable uses the same arrays that the user interface thread writes to. As soon as you call executor.execute(insertHandler); , there is no guarantee that the user interface thread will not receive another sensor event and will change one of the array values ​​before Runnable writes them to the database. You seem to understand this part.

To fix this, I would not recommend using a synchronized block at all, since it seems like you just want to write any values ​​stored in arrays when diffTime > POLL_FREQUENCY . The onSensorChanged(...) method onSensorChanged(...) will only be called on the user interface thread in your code, so you don’t have to worry about another thread changing the value of the arrays in this method.

With all this, it says that you can save the current values ​​of arrays in a new instance of your Runnable class. I know that in the previous article it was suggested to use the same instance, but that would not make any noticeable difference. You can even check by opening Android Monitor and checking your memory usage as an application. Saving the current values, it doesn’t matter now whether onSensorChanged() is called again before you write out the data, because you already have a copy of the data you need that will not change.

Here is what I suggest in the code:

 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 } } 

And then when you add Runnable to executor , use:

 Runnable insertHandler = new InsertHandler(accelerometerMatrix, accelerometerWorldMatrix, gyroscopeMatrix, gravityMatrix, magneticMatrix, rotationMatrix); executor.execute(insertHandler); 
+2
source

Source: https://habr.com/ru/post/1246399/


All Articles